并发编程一:Synchronized的使用及分析

本文主要为了分析Synchronized的使用及分析,全程例子跟踪讲解,妈妈再也不用担心你的编程。(Lock等后续会讲解)

首先我们先看个例子:

public class MyThread implements Runnable{
    // 定义一个变量
    static int i=0;
    // 方法 使内部变量 加加递增
    public void add(){
        i++;
    }

    // 实现Runnable重写线程run方法
    @Override
    public void run() {
        for(int i=0;i<10000;i++){
            add();
        }
    }

    // 主函数 程序入口(我好像多余写,但是我就想写,怎样?)
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        // 创建一个线程 t1
        Thread t1=new Thread(myThread);
        // 创建一个线程 t2
        Thread t2=new Thread(myThread);
        // 启动线程
        t1.start();
        t2.start();
        // join不知道的自己百度,简单解释下:调用join的线程必须执行完才能继续执行主线程,此处也可以用sleep
        t1.join();t2.join();
        System.out.printf("结果:"+i);
    }
}

3次运行结果:

 

从结果上我们可以发现,有一次结果是正确的,俩次不正确。这就是线程不安全的。下面我们在add方法上添加synchronized再进行测试

public class MyThread implements Runnable{
    // 定义一个变量
    static int i=0;
    // 方法 使内部变量 加加递增
    public synchronized void add(){
        i++;
    }

    // 实现Runnable重写线程run方法
    @Override
    public void run() {
        for(int i=0;i<10000;i++){
            add();
        }
    }

    // 主函数 程序入口(我好像多余写,但是我就想写,怎样?)
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        // 创建一个线程 t1
        Thread t1=new Thread(myThread);
        // 创建一个线程 t2
        Thread t2=new Thread(myThread);
        // 启动线程
        t1.start();
        t2.start();
        // join不知道的自己百度,简单解释下:调用join的线程必须执行完才能继续执行主线程,此处也可以用sleep
        t1.join();t2.join();
        System.out.printf("结果:"+i);
    }
}

继续看3次运行结果:

 

哈哈哈 我们会发现 全都是 20000了,都是正确的结果。看来添加synchronized 可以保证线程的安全。你以为这就完事了,刚刚开始而已。来我们再来看个例子:

public class MyThread implements Runnable{
    // 定义一个变量
    static int i=0;
    // 方法 使内部变量 加加递增
    public synchronized void add(){
        i++;
    }

    // 实现Runnable重写线程run方法
    @Override
    public void run() {
        for(int i=0;i<10000;i++){
            add();
        }
    }

    // 主函数 程序入口(我好像多余写,但是我就想写,怎样?)
    public static void main(String[] args) throws InterruptedException {
        //MyThread myThread = new MyThread();
        // 创建一个线程 t1
        Thread t1=new Thread(new MyThread());
        // 创建一个线程 t2
        Thread t2=new Thread(new MyThread());
        // 启动线程
        t1.start();
        t2.start();
        // join不知道的自己百度,简单解释下:调用join的线程必须执行完才能继续执行主线程,此处也可以用sleep
        t1.join();t2.join();
        System.out.printf("结果:"+i);
    }
}

这段代码add方法上也添加了synchronize,但是我们为每个线程创建了一个MyThread对象而不是上面的两个线程用一个对象。

下面继续看3次的运行结果:

 

卧槽了吧,哈哈怎么方法加了synchonized 线程还不安全。这里面就涉及到了对象锁和类锁的问题。有空再写吧写这玩意浪费时间。直接总结下吧  static synchonized和synchonized (类名.class) 可以解决问题  这俩都是类锁,类只有一个文件所以只能有一个线程获取到锁所以线程安全,至于对象锁也不是没用对象锁保证的是单个对象操作的并发问题

猜你喜欢

转载自blog.csdn.net/weixin_41485592/article/details/81193706
今日推荐