线程安全问题

两个窗口同时打印一张票的问题:
线程售票窗口1:抢到cpu资源开始执行run方法,拿到的票是44号票,然后执行sleep方法,此时线程1进入阻塞状态,没有执行减减的操作;线程3此时拿到cpu资源开始执行run方法,一进来发现ticket=44,然后线程3执行sleep方法,线程3开始进入阻塞状态;
然后,线程1sleep完毕,继续开始抢占c'pu资源,抢占后,执行ticket--;输出43;并释放cpu资源;此时线程3,sleep执行完毕,开始抢占cpu资源,抢占后,执行ticket--,输出43;最后窗口1和窗口3同时卖了44号票,出现了严重的线程安全问题。
1.问题分析

综上所述:
线程安全的根本原因:
1.多个线程在同时操作共享数据;
2.操作共享数据的线程代码有多条;
3.多个线程对共享数据有写的操作。
2.解决方法
要解决以上的线程问题,只要在某个线程修改共享资源的时候,其他线程不能修改资源,等待修改完毕以后,才能去抢夺c'pu资源,完成对应的操作,保证了数据的同步性,解决了线程不安全的现象。
为了保证每个线程都能够正常执行共享资源操作,java映入了7种线程同步的方式
1.同步代码块(synchronized)

首先得定义锁对象 Object object=new Object();

2.同步方法(synchronized)
使用synchronized修饰的方法,就叫做同步方法,保证线程A执行该方法的时候,其他线程只能在方法外等着。
public synchronized void 方法名(){
可能会产生线程安全问题的代码
}
同步锁是谁的问题?
1. 对于非static方法的同步锁就是this,这个锁对象就是调用当前方法的对象的实例
比如说new了一个Ticket,用Ticket调用这个同步方法,那这个锁对象就是这个实例
2.对于static方法,同步锁是当前方法所在类对应得字节码对象 如Ticket.class
实例代码:


3.同步锁(ReenreantLock)


案例:


注意事项:使用重入锁时要却确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。一个lock对应一个unlock
公平锁是指当锁可用时,在锁上等待时间最长的线程将获得锁的使用权。而非公平锁则随机分配这种使用权。

