在同一个JVM下,如何确保线程安全?
在我们所熟悉的前提下,主要通过以下俩种手段确保线程的安全性。
1、synchronized关键词
2、锁
什么是锁?
通俗的讲,就是每家每户出门的时候都是需要锁门的,避免小偷光顾!在我们Java里上锁的方式有ReentrantLock、ReentrantReadWriteLock俩种实现方式。此处我理解的加锁处理数据的方式是:串行。
ReentrantLock保证线程安全
需求:
我们现在总共有10张通往大理的飞机票,并且有三个售票窗口进行售票,该如何设计购票程序,使其不会有少售,多售的情况出现?
定义三个售票窗口如下:
MyRunable myRunable = new MyRunable();
Thread thread = new Thread(myRunable, "窗口一");
Thread thread1 = new Thread(myRunable, "窗口二");
Thread thread2 = new Thread(myRunable, "窗口三");
thread.start();
thread1.start();
thread2.start();
定义具体售票操作如下:
public class MyRunable implements Runnable {
private int tickets = 10; // 定义十张票
private final Lock lock = new ReentrantLock();
@Override
public void run() {
while (true){
lock.lock();
if (tickets > 0){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +" 出售了第 " + tickets-- + " 张票");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}else{
lock.unlock();
}
}
}
}
在我们加锁的前提下,切记需要在final中去释放锁,不然会造成死锁状态!
购票期望结果:
ReentrantReadWriteLock保证线程安全
需求:
我们现在总共有10张通往大理的飞机票,并且有三个售票窗口进行售票,该如何设计购票程序,使其不会有少售,多售的情况出现?
定义三个售票窗口如下:
MyRunableReadWrite myRunable = new MyRunableReadWrite();
Thread thread = new Thread(myRunable, "窗口一");
Thread thread1 = new Thread(myRunable, "窗口二");
Thread thread2 = new Thread(myRunable, "窗口三");
thread.start();
thread1.start();
thread2.start();
定义具体售票操作如下:
public class MyRunableReadWrite implements Runnable {
private int tickets = 10; // 定义十张票
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
@Override
public void run() {
while (true){
readWriteLock.readLock().lock();
if (tickets > 0){
try {
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +" 出售了第 " + tickets-- + " 张票");
}catch (Exception e){
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock();
}
}else {
readWriteLock.readLock().unlock();
}
}
}
}
读写锁,在我们日常开发中也是及其重要的一个锁,具体理解如下:我们程序首先给读锁加锁,读到数据进行读锁解锁操作,并给写锁加锁,等数据写完之后给写锁进行解锁操作。必须进行解锁操作,否则会造成死锁。
购票期望结果: