A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

    本文主要向大家介绍了多线程的代码安全问题的解决办法
    1,利用同步代码块的方式
    2,调用Lock类的lock与unlock方法
    那么什么是线程安全呢?
    当多个线程一起运行时,在线程中的run方法,有可能运行一半,就失去了CPU的使用权,这时如果对成员变量有所操作,会影响别的线程在判断时的数据,因此会发生数据异常的情况。所以为了防止这种情况的发生,我们通过上锁的方式,将一个循环下的所有代码锁起来,保证它们是按照顺序执行下来的,这样就不会发生数据错乱的情况。
    细心的同学会发现,关于同步代码块的synchronized方法的参数在什么时候用(this)在什么时候用Oject对象呢?
    这也是这篇帖子的重点!!!
    Runnable接口的步骤是:
    1、创建任务对象
    2、创建Thread线程对象参数为任务对象
    3、调用start()方法,完成多线程。
     所以我们在创建任务时既可以创建多个任务,也可以创建一个任务,当run方法中对成员变量有操作是,一般是创建一个任务对象,如果没有可以创建多个任务对象,这时我们要注意下面的事情:
     synchronized方法中定义的锁对象,当多个线程调用时一定要保证锁对象唯一,用this当锁对象时保证创建的对象即调用线程的对象唯一,当定义一个Object类的成员变量时,就不必担心锁对象不唯一,即可以创建多个任务对象来调用线程
     我们如果用lock类进行上锁,就不可和同步代码块synchronized一起使用,会发生线程不安全异常,所以保证锁对象唯一性是至关重要的!!!

//代码实现部分;
//第一部分:
//首先定义一个线程实现Runnable接口,用同步代码块的方式实现线程安全
public class SynchronizedDemo implements Runnable{
       //定义成员变量
        private String name;
        private String sex;
        private int age;
        //创建一个Object类的对象作为锁对象
        Object lock = new Object();
       //方法的满参构造
        public SynchronizedDemo(String name,String sex,int age) {
                super();
                this.name = name;
                this.sex = sex;
                this.age = age;
        }
        //重写接口的run方法
        @Override
        public void run() {
                        // TODO Auto-generated method stub
                        //同步代码块
                while(true) {
                      //用synchronized的同步代码块的方式将循环体锁住
                        synchronized(lock) {
                                System.out.println(Thread.currentThread().getName()+"运行的信息:");
                                System.out.println("姓名:"+name);
                                System.out.println("性别"+sex);
                                System.out.println("年龄"+age);
                        }
                }
        }
}
//第二部分:
//导包
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//创建一个类完成用lock的方法进行锁定实现线程安全
public class LockDemo implements Runnable{
        //创建Lock类对象(多态);
        Lock l = new ReentrantLock();
       //重写接口的run方法
        @Override
        public void run() {
                while(true){
                       //在循环体内上锁
                        l.lock();
                        System.out.println("第一条信息");
                        System.out.println("第二条信息");
                        System.out.println("第三条信息");
                        System.out.println("第四条信息");
                        System.out.println("第五条信息");
                      //调用unlock方法开锁
                        l.unlock();
                }
        }       
}
//第三部分:
//测试类
//测试类进行了两种情况的练习,第一种是lock与synchronized一起用结果为线程不安全,因为创建了两个对象。
//第二种是用synchronized方法的两个不同的锁对象进行测试,如果锁对象为this且创建了两个任务对象,线程不安全。
public class Test {
        public static void main(String[] args) {
                SynchronizedDemo sd = new SynchronizedDemo("男枪","男",30);
                SynchronizedDemo ds = new SynchronizedDemo("安妮","女",16);
                //LockDemo ld = new LockDemo();
                Thread t = new Thread(sd,"第一条线程");
                Thread tr = new Thread(ds,"第二条线程");
                //Thread th = new Thread(ld);
                t.start();
                //th.start();
                tr.start();
        }
}


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马