【JAVA之多线程】3.线程同步

一、线程同步

  • 访问同一个资源的多个线程之间进行协调的过程,就叫做线程同步。
public class Demo {
    public static void main(String[] args){
        T d = new T();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();
    }
}

class T implements Runnable {
    private int ticket = 5;
    public void run(){
        while (true){
            if (ticket > 0) {
                try {
                    Thread.sleep(20);//即使不添加sleep,在现实运行中也会出现安全问题
                } catch (Exception e) {}    
                sopl(Thread.currentThread().getName() + ": " + ticket--);
            }   
        }
    }
}
//运行结果:(会出现0号错票)
Thread-1: 5
Thread-0: 4
Thread-1: 2
Thread-0: 3
Thread-1: 0
Thread-0: 1
//原因:当多条语句在操作同一个共享数据时,一个线程对多条语句只执行
//了一部分,还没有执行完,另一个线程参与进来执行,导致结果出现错误

二、解决办法

  • 目的:多条线程在操作共享数据时,只让一个线程执行完在执行其他线程。即,在执行过程中,其他线程不可以参与执行。
  • 第一种方法:synchronized(this)锁定当前对象
synchronized(this) {
    //需要被同步的代码,哪个是共享数据,则哪部分代码需要被同步
}
public class Demo {
    public static void main(String[] args){
        T d = new T();
        Thread t1 = new Thread(d);
        Thread t2 = new Thread(d);
        t1.start();
        t2.start();
    }
}

class T implements Runnable {
    private int ticket = 5;
    public void run(){
        while (true){
            synchronized (this) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(20);
                    } catch (Exception e) {}    
                    System.out.println(Thread.currentThread().getName() + ": " + ticket--);
                }
            }
        }
    }
}
//运行结果没有出现0
  • 简便写法
class T implements Runnable {
    private int ticket = 5;
    Object obj = new Object();
    public void run(){
        while (true){
            show();//this.show();
        }
    }
    public synchronized void show() {//this
        if (ticket > 0) {
            try {
                Thread.sleep(20);
            } catch (Exception e) {}    
            sopl(Thread.currentThread().getName() + ": " + ticket--);
        }
    }
}
  • 不能对run方法同步,否则当某一个线程开始执行,一定会等当前线程执行完,其他线程才能得到执行权。所以将需要同步的代码单独拿出来放在一个普通方法中,对该方法进行同步。

你可能感兴趣的:(【JAVA之多线程】3.线程同步)