Java中的同步机制解决线程安全问题
什么是线程安全呢?就是我们开启多线程的时候,如何解决并发的问题,比如之前的买火车票问题,出现了不同的窗口卖同一张票的现象,那么这个是不允许的,这个就是资源占用的问题,如果想出一个方法,能让窗口1卖这一张票,另外的只能等待,这样就解决了上述的问题了。那么,在Java中有三种常见的方法解决线程安全。
-
同步代码块
所谓的同步代码块就是用synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
public class TiceketSold implements Runnable{ //定义一个票数 int num = 10; Object lock = new Object(); @Override public void run() { while (true){ synchronized (lock){ //模拟卖票的时间(100ms) if (num == 0){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+num--+"张票"); } } } public static void main(String[] args) { TiceketSold tk = new TiceketSold(); new Thread(tk,"xiao").start(); new Thread(tk,"xddd").start(); new Thread(tk,"xggg").start(); } }
-
同步方法
这个其实类似于上面,不过是用一个方法将有哦线程安全的代码抽离出来写一个方法,然后使用的时候调用这个方法即可。
public class TiceketSold01 implements Runnable{ //定义一个票数 int num = 10; @Override public void run() { soldTicket(); } //同步方法 public synchronized void soldTicket(){ while (true){ //模拟卖票的时间(100ms) if (num == 0){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+num--+"张票"); } } public static void main(String[] args) { TiceketSold01 tk = new TiceketSold01(); new Thread(tk,"xiao").start(); new Thread(tk,"xddd").start(); new Thread(tk,"xggg").start(); } }
-
Lock锁
java.util.concurrent.locks.Lock
机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock()
:加同步锁。public void unlock()
:释放同步锁。public class TiceketSold02 implements Runnable{ //定义一个票数 int num = 10; Lock lock = new ReentrantLock();//定义lock对象 @Override public void run() { while (true){ //模拟卖票的时间(100ms) lock.lock();//加锁 try { if (num == 0){ break; } Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+num--+"张票"); lock.unlock();//释放锁 } } public static void main(String[] args) { TiceketSold02 tk = new TiceketSold02(); new Thread(tk,"xiao").start(); new Thread(tk,"xddd").start(); new Thread(tk,"xggg").start(); } }