线程安全,syncronized 用法

1,为什么有线程安全问题?

当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。

 

public class TrainThread implements Runnable {

    // 定义初始化票100张
    private int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (ticketCount > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
            ticketCount--;
        }
    }

}
public class App {
    public static void main(String[] args) throws InterruptedException {
        TrainThread trainThread = new TrainThread();
        
        //模拟了两个线程,必须都用同一个Runnable 的子类对象,才能叫 实现资源的共享
        Thread thread1 = new Thread(trainThread);
        Thread thread2 = new Thread(trainThread);
        thread1.start();
        thread2.start();
    }

}

可能出现的情况:同时卖了某一张票

Thread-1卖出了第1张票
Thread-1卖出了第2张票
Thread-0卖出了第1张票
Thread-0卖出了第4张票
Thread-1卖出了第3张票
Thread-1卖出了第6张票

 

:为什么使用线程同步或使用锁能解决线程安全问题呢?

:将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,让后才能让其他线程进行执行。这样的话就可以解决线程不安全问题。

:什么是多线程之间同步?

:当多个线程共享同一个资源,不会受到其他线程的干扰

 

2, 实现线程同步,syncronized 的用法

解决一:

锁对象

syncronized 同步代码块:就是将可能会发生线程安全问题的代码,给包括起来。

synchronized(同一个数据){

 可能会发生线程冲突问题

}

public class TrainThread implements Runnable {

    // 定义初始化票100张
    private int ticketCount = 100;
    //定义了一个共享的对象
    private Object obj = new Object();

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                ticketCount--;
            }
        }

    }

}

解决二:

同步函数,

在方法上修饰synchronized 称为同步函数

锁方法

public class TrainThread implements Runnable {

    // 定义初始化票100张
    private int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        sale();
    }

    private synchronized void sale() {
        while (ticketCount > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
            ticketCount--;
        }
    }
}

 

3,同步函数,所方法,其实是this 锁

证明,两个线程,一个线程走同步代码块,(锁住了自定义object对象)的代码,

另一个走同步函数,锁方法的的代码,结果数据有冲突,证明了syncronized 没有效,并没有锁住同一资源

将锁对象的object 换成this,则没有数据冲突

4,是静态同步函数?

方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。

静态的同步函数使用的锁是  该函数所属字节码文件对象

还是加syncronized,和之前没有区别,锁方法

public class TrainThread implements Runnable {

    // 定义初始化票100张
    private static int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sale();
    }

    private  synchronized static void sale() {
        while (ticketCount > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
            ticketCount--;
        }
    }
}

锁当前类的的字节码文件的对象,不是this,或者自定义的对象

public class TrainThread implements Runnable {

    // 定义初始化票100张
    private static int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (TrainThread.class) {
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
                ticketCount--;
            }
        }
    }

}

 

posted @ 2019-06-13 15:57  Chris,Cai  阅读(388)  评论(0编辑  收藏  举报