多线程同步 (一)——synchronized关键字

之前在Java内存模型与多线程中介绍过,在并发编程中,非常重要的两个问题是:通信和同步
本博客主要对如何使用synchronized关键字实现线程间同步问题的自我学习总结。

1. 线程间的同步

同步:是用于控制不同线程间操作发生相对顺序的机制。

注:

  • 有两个词语“线程安全”和“非线程安全”,同步保障了线程安全。因为非线程安全的发生,就是由于在
    线程的创建和启动中提到的线程因其与生俱来的“随机性”造成的,所以如果线程的执行被控制为有序的,那么就不会有那么多麻烦了;
  • 非线程安全问题存在于共享变量中,即成员变量/实例变量,而不是方法内部的局部变量,因此只有共享资源的读写访问才需要同步。

2. synchronized关键字的使用

  • 修饰方法,可以修饰普通的实例方法,或者静态的类方法;
  • 修饰代码块;

例子: 创建3个线程,对变量num进行有序+1操作,循环100次。

代码实例1:

/*
 * 不使用synchrinized关键字
 */
public class Test_synchronized implements Runnable {

    private int num = 0;
    @Override
    public void run() {
        printNum();
    }
    public void printNum(){
        for(int i=0; i<100; i++){
            num++;
            System.out.println(Thread.currentThread().getName()+": "+num);
        }
    }

    public static void main(String[] args) {
        Test_synchronized r = new Test_synchronized();
        for(int i=0; i<3; i++){

            Thread t = new Thread(r);
            t.start();
        }
    }   
}

运行结果1:

这里写图片描述
……中间打印省略……
这里写图片描述

其中num是共享变量,所以3线程同时对该变量进行读写时,在没有同步的情况下,是非线程安全的,
用关键字synchronized修饰方法printNum()后,代码和运行效果如下:

代码实例2:

/*
 * 使用synchrinized关键字修饰实例方法printNum()
 */
public class Test_synchronized implements Runnable {

    private int num = 0;
    @Override
    public void run() {
        printNum();
    }
    synchronized public void printNum(){
        for(int i=0; i<100; i++){
            num++;
            System.out.println(num);
        }
    }

    public static void main(String[] args) {
        Test_synchronized r = new Test_synchronized();
        for(int i=0; i<3; i++){

            Thread t = new Thread(r);
            t.start();
        }
    }
}

运行结果2:

这里写图片描述
……中间打印省略……
这里写图片描述

共享变量num实现了有序递增。

你可能感兴趣的:(多线程)