线程安全
什么情况出现线程安全
当多个线程操作同一个资源时,则出现线程安全问题。
线程安全的解决方式
第一种:使用synchronized自动锁 优点:可以使用在方法或代码块上
第二种: 使用Lock手动锁。 优点:更加灵活,但是释放锁必须在finally中
二者的区别:第一种可以自动加锁和释放锁,不会出现死锁问题
第二种只能使用在代码块,需要手动加锁和释放锁
使用锁相对于把原来的异步转换为同步操作。
一、synchronized
public class SellTicket implements Runnable {
private int tick = 100;
private static Object o = new Object();
//使用在代码块上
public void run() {
while (true) {
synchronized (this) {
if (tick > 0) {
tick--;
System.out.println("卖了一张票;剩余:" + tick + "张");
} else {
break;
}
}
}
}
//使用在方法上
public synchronized void sell(){
if (tick > 0) {
tick--;
System.out.println( "卖了一张票;剩余:" + tick + "张");
}
}
}
二、Lock
public class SellTicket implements Runnable {
private int tick = 100;
private Lock l = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
l.lock();//加锁
if (tick > 0) {
tick--;
System.out.println("卖了一张票;剩余:" + tick + "张");
} else {
break;
}
} finally {
l.unlock();//解锁
}
}
}
}
死锁
线程A用锁A,需要嵌套使用锁B,线程B使用锁B,需要嵌套使用锁A,两个线程互相锁着对方需要获取的锁资源,可能会出现程序堵塞造成死锁
解决方式
一、避免使用锁嵌套
二、使用Lock类中tryLock设置超时时间
三、使用安全类java.util.concurrent下的类简称JUC
线程通信和线程状态
线程通信的方法
wait:会自动释放锁资源,进入等待状态
notify:随机唤醒一个等待中的线程
notifyAll:唤醒所有等待中的线程
线程状态
NEW:新建状态。 RUNNABLE:就绪状态和运行状态 BLOCKED:堵塞状态 WAITING:等待状态 TIMED_WAITING:时间等待 TERMINATED:终止。