Java:多线程同步机制

发布于 2020-12-27  1594 次阅读


Java是如何做到线程同步的呢?

  1. 在需要同步的方法的 方法签名中加上 synchronized关键字
  2. 使用synchronized关键字对需要进行同步的代码块进行同步
  3. 使用java.util.concurrent.lock包中Lock对象(JDK1.8)
1.在需要同步的方法的 方法签名中加上 synchronized关键字

public class Data {
    private int mVal = 0;
    
    public void setDate(int mVal) {
        this.mVal = mVal;
    }
    public int getDate() {
        return mVal;
    }
}

public class MyThread implements Runnable{
    private Data mData = new Data();
    
    
    @Override//让多个线程共享一个数据
    public synchronized void run() {
            int tmp = mData.getDate();
            ++tmp;
            mData.setDate(tmp);
            System.out.println(Thread.currentThread().getName()+"|"+mData.getDate());
    }
    
    
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(myThread);
            thread.start();
        }
    }
}

//打印的结果
Thread-0|1
Thread-4|2
Thread-3|3
Thread-2|4
Thread-1|5

public class MyThread implements Runnable{
    private Data mData = new Data();
    
    
    @Override//注释了synchronized关键字后再看结果
    public /*synchronized*/ void run() {
            int tmp = mData.getDate();
            ++tmp;
            mData.setDate(tmp);
            System.out.println(Thread.currentThread().getName()+"|"+mData.getDate());
    }
    
    
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(myThread);
            thread.start();
        }
    }

}

//注释了synchronized关键字后
Thread-0|2
Thread-4|5
Thread-3|4
Thread-2|3
Thread-1|2
//需要注意的是,运行的结果肯定每次都是不同的,原因:线程抢占到资源的顺序
2. 使用synchronized关键字对需要进行同步的代码块进行同步 (Data类还是一样)

public class MyThread implements Runnable{
    private Data mData = new Data();
    
    
    @Override//使用synchronized代码块(同步块)
    public void run() {
        synchronized (this) {
            int tmp = mData.getDate();
            ++tmp;
            mData.setDate(tmp);
            System.out.println(Thread.currentThread().getName()+"|"+mData.getDate());
        }       
    }
    
    
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(myThread);
            thread.start();
        }
    }

}

//打印的结果
Thread-0|1
Thread-4|2
Thread-3|3
Thread-2|4
Thread-1|5
3. 使用java.util.concurrent.lock包中Lock对象(JDK1.8) 【有需要的时候再补充】

synchronized使用时需要注意的一些地方:

被synchronized关键字修饰的代码块在被线程执行之前,首先要拿到被同步对象的锁,并且一个对象仅仅是只有一个锁,比如上面被synchronized代码,首先那个方法需要拿到当前对象的锁,如果当前的锁已经被其它线程拿走了,那么还没抢到锁的线程将从可运行状态转变为阻塞状态,只有当拿到锁的线程执行完同步块的代码后,就释放锁,让给别的线程的、这样就可以保证数据的完整性!


欢迎欢迎~热烈欢迎~