什么是线程安全问题
当多个线程共享同一个成员变量或者静态变量 . 做写的操作肯定会收到其他线程的干扰,导致数据有问题这种现象叫做线程安全问题(做读的操作不会发生数据冲突问题)
示例 :
class threadTrain1 implements Runnable { // 重写run()方法 private static int count = 100; public void run() { while (count > 0) { try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } sale(); } } public void sale() { if (count > 0) { System.out.println(Thread.currentThread().getName() + " 出售 第 " + (100 - count + 1) + " 张票"); count--; } } } public class thread_dame_1 { public static void main(String[] args) { threadTrain1 thread1 = new threadTrain1(); Thread t1 = new Thread(thread1, " 一号窗口 "); Thread t2 = new Thread(thread1, " 二号窗口 "); t1.start(); t2.start(); } }
结果 :
部分票重复出售
多个线程共享同一个成员变量时会发生数据冲突
解决线程安全问题
使用多线程之间同步 synchronized 或使用锁 (lock) 解决线程安全
什么地方需要加锁
线程同步保证只有一个线程进行访问
必须要有2个线程以上,需要发生同步
当多个线程想同步时必须用同一把锁,线程同步共享一个资源不会受到其他线程的干扰
同步代码
synchronized(同一个对象(锁))//这个对象可以为任意对象 可以使用 this 锁 { //可能发生线程冲突问题代码 }
示例 :
public void sale() { synchronized (this) { if (count > 0) { System.out.println(Thread.currentThread().getName() + " 出售 第 " + (100 - count + 1) + " 张票"); count--; } } }
或者 :
( 修饰在方法上 为 同步函数 )
public synchronized void sale() {
if (count > 0) {
System.out.println(Thread.currentThread().getName() + " 出售 第 " + (100 - count + 1) + " 张票");
count--;
}
}
结果 :
静态同步函数
静态同步函数被 static 修饰的同步函数
静态不能用 this 静态同步函数使用的锁是 该静态函数所属的 字节码
字节码可以使用 getClass()方法获取 或者 直接 类名.class 表示
示例 :
public static void sale() { synchronized (threadTrain1.class) { if (count > 0) { System.out.println(Thread.currentThread().getName() + " 出售 第 " + (100 - count + 1) + " 张票"); count--; } } }
多线程三大特性
原子性 , 可见性 , 有序性
原子性 : 保证数据一致, 保证线程安全
可见性 : 多个线程访问同一个变量时 , 一个线程修改了值 , 其他线程能立即得到修改的值,若2个线程不在同一个cpu , 那么线程a 改变了值 , b线程使用还是原来的值 , a 修改的值 b 没有看到 这就是可见性
有序性 : 程序执行的顺序按照先后顺序执行 如之前的 join()
原文:https://www.cnblogs.com/chenkuijiang/p/12181574.html