线程安全,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--; } } } }
Aimer,c'est partager