前言
在使用多线程享受其带来效率提升的同时,也存在许多安全隐患,我们该如何处理和预防多线程中可能会出现的问题,这就要了解线程安全的一些知识。
一、什么是线程安全和线程不安全?
多个线程访问同一个资源,有可能出现线程不安全的问题,这种情况就是线程出现了安全问题。
线程安全
此时代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
线程不安全
就是不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。
二、synchronized 关键字的使用
解决多线程的方案:加锁(synchronized)
synchronized ("锁"){
System.out.println("xxxxxx");
System.out.println("xxxxxx");
System.out.println("xxxxxx");
}
可以使用一把锁,把需要锁住的代码(关键性代码)给锁住,就线程安全了。
关键性的代码: 关于同一资源的代码: ticketNum 就是同一资源。
什么样的东西可以当锁?
多个线程中的唯一性内容就可以当锁,锁必须是唯一 的。
synchronized 除了可以锁代码块,还可以锁方法
synchronized 还可以作用在方法上,方法又分为两种: 普通方法和静态方法
修饰普通方法:锁是什么?
public synchronized void run()
锁就是这个方法对应的类的实例化对象,比如Ticket ticket = new Ticket(); ticket 就是锁。
修饰静态方法,锁是什么?
public synchronized static void run()
这个锁就是该方法对应的类的字节码文件 Tikcket.class
选择问题:
什么时候锁方法,什么时候锁代码块?
优先使用代码块, 锁可以提供安全,但是效率低。
锁住的代码:每一时刻只能有一个线程使用,使用完再释放,线程一多,就阻塞了。
方法中的代码可能很多,只有一部分出现了线程安全问题,只需要考虑那一部分即可
三、案例分析
1.四线程卖票冲突
代码如下(示例):
public class MyRunnable implements Runnable{
int ticketNum=100;//设置票数 总共100
boolean flag=true;
@Override
public void run() {
while (flag) {
if (ticketNum == 0) {
System.out.println("卖完了");
flag = false;
} else {
System.out.println(Thread