1.多线程并发的安全问题:
多线程环境下,多个线程是并发执行的,并且是抢占式执行,线程的执行顺序不确定,此时如果多个线程同时区操作共享资源,就可能出现数据的先后错乱:入银行的多次并发取钱问题,可能导致钱数为负;
举例卖票问题:
public class ThreadConrrent {
public static int tickets = 10;
public static void main(String[] args) {
new Thread(new Saler()).start();
new Thread(new Saler()).start();
}
}
class Saler implements Runnable{
@Override
public void run() {
//当多个线程执行到此,票有一张,所以每个线程都并发执行就出现了负票的情况
while(ThreadDemo06.tickets>0){
ThreadDemo06.tickets--;
System.out.println(Thread.currentThread().getId()+"窗口,卖出去了一张票。。剩余票数为"+ThreadDemo06.tickets);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.多线程并发安全问题产生的条件
- 有共享资源
- 有多线程并发操作了共享资源
- 有多线程并发操作共享资源且设计到增删改
3.解决多线程并发安全问题
关键是破坏并发安全问题产生的条件
- 禁止共享资源 -- ThreadLocal
- 禁止多线程并发操作 - 加锁 Syncronized lock
- 禁止多线程修改 - lock 读写锁
解决并发问题引出的死锁问题:
死锁是一种并发锁定的特殊状态,指的是多个共享资源,一部分线程持有另一部分资源的锁,另一部分线程持有另外的资源,导致各自持有各自的锁,但需要另一部分资源的锁为被释放,这样就进入了一个相互等待的状态,都无法执行,称之产生了死锁。
死锁是一种特殊的并发状态,程序中药尽力避免死锁。
死锁产生的条件
多把锁进行了同步嵌套
解决死锁
避免死锁
避免锁的同步嵌套
检测并打断死锁
有时无法进行避免死锁的操作,此时只能不停的检测是否有死锁产生,如果有死锁产生,则打断死锁,所谓的打断死锁,就是将造成死锁的某一线程错误退出,打断对锁互相要求的环,从而使程序可以正常运行下去
并发度高时,反复多次创建线程会造成资源的浪费。所以java中引入了线程池解决高并发创建线程的问题。
下一节线程池的创建