什么是线程安全问题?
多个线程,访问同一资源,出现了问题,就是线程安全问题(数据不准确,或者直接报错)
1)错误演示:
public class Demo04 {static int tickedNum = 100;/*火车票剩余100张,四个窗口同时卖票,不允许超卖*/public static void main(String[] args) {Runnable runnable = ()->{while(tickedNum > 0){System.out.println(Thread.currentThread().getName()+"卖出了第"+(100-tickedNum+1)+"张票");tickedNum--;}};new Thread(runnable,"窗口1").start();new Thread(runnable,"窗口2").start();new Thread(runnable,"窗口3").start();new Thread(runnable,"窗口4").start();}
}
出现线程安全:
多线程出现安全问题的原因是:多个线程抢占了同一个资源,在资源最关键的时刻,相互抢夺,出现了问题。
解决办法:在关键步骤,不能抢夺。
2)解决方案
public class Demo04 {static int tickedNum = 100;/*火车票剩余100张,四个窗口同时卖票,不允许超卖*/public static void main(String[] args) {Object obj = new Object();Runnable runnable = () -> {while(true){/*为什么在这个地方放了一个字符串 "锁"啥是锁? 就是用一个公共的对象,多个线程中这个对象必须是只有独一份,才能当锁锁住的代码,必须一个线程释放了这个锁,另一个线程才能获取到,谁获取到这个锁谁就可以执行代码块的内容一个字符串,本身在内存中就只有一份,在常量池中,第一次出现创建该对象,第二次出现就从常量池中拿。一般都通过一个对象来充当,但是不能new*/synchronized (obj){if(tickedNum > 0){System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - tickedNum + 1) + "张票");tickedNum--;}else{break;}}}// 缺点:会超卖/*while (tickedNum > 0) {synchronized ("锁") {System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - tickedNum + 1) + "张票");tickedNum--;}}*/};new Thread(runnable, "窗口1").start();new Thread(runnable, "窗口2").start();new Thread(runnable, "窗口3").start();new Thread(runnable, "窗口4").start();}
}
synchronized 的用法
1)修饰代码块
2)修饰方法
1) 修饰静态方法 Dog.class
2) 修饰普通方法 Dog dog =new Dog();
public class Demo05 {// 该方法是线程安全的,每次只能有一个线程使用该方法// 这个地方的锁指的是谁? 静态方法加了锁,该锁指的是 这个类的class对象 Demo05.classpublic synchronized static void show(){System.out.println("Hello World!");}// 非静态方法,锁指的是谁? 该类的一个实例化对象// Demo05 ddd = new Demo05();// Demo05 ccc = new Demo05();public synchronized void show2(){System.out.println("Hello World!");}public static void main(String[] args) {// 锁指的是字符串 "锁"Object o = new Object();synchronized (o){System.out.println("哈哈哈");}}
}