此篇博客已售票例子为例,所以首先看一个synchronized(同步锁机制)的案例
synchronized(同步锁机制)的案例
package android.java.thread19; /** * 售票线程 */ class Booking implements Runnable { /** * 模拟票的总算 10张票 */ private int ticket = 10; @Override public void run() { while (true) { /** * 加入了同步代码块的代码synchronized, * 不管CPU如何疯狂的切换执行, * 只要同步代码块里面的代码没有执行完, * 就不准其他线程进来执行 * 这样就保证了多线程操作共享数据的安全新 */ synchronized (Booking.class) { // 同步操作共享数据的代码 if (ticket > 0) { // 让线程在这里停一下,会更加容易复现线程的安全问题,就算不加这行代码,安全问题依然有 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("名称:" + Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票"); ticket--; } } } } } /** * 售票案例 */ public class LockTestDemo { public static void main(String[] args) { /** * 定义Runnable实现类Booking,此实现类Booking不是线程,此实现类Booking给四个Thread去执行的 */ Runnable booking = new Booking(); // 实例化线程对象 Thread thread1 = new Thread(booking); // 此实现类Booking给Thread去执行的 Thread thread2 = new Thread(booking); // 此实现类Booking给Thread去执行的 Thread thread3 = new Thread(booking); // 此实现类Booking给Thread去执行的 Thread thread4 = new Thread(booking); // 此实现类Booking给Thread去执行的 // 开启启动线程 thread1.start(); // 启动第Thread-0窗口 执行卖票任务 thread2.start(); // 启动第Thread-1窗口 执行卖票任务 thread3.start(); // 启动第Thread-2窗口 执行卖票任务 thread4.start(); // 启动第Thread-3窗口 执行卖票任务 } }
执行结果:
在JDK1.5以前是使用synchronized(同步锁机制),以上 (synchronized(同步锁机制)的案例)就是使用synchronized同步锁机制
synchronized同步锁机制,是隐式的,什么时候锁住,什么时候释放锁,锁是什么锁??...... ,这个是看不到的,例如:
public synchronized(锁??是当前this) void exit() { // .... }
public static synchronized(锁??是 当前类名.class) void actionTicket() { // ..... }
synchronized (厕所门显示无人 ??) { // 上厕所任务 ........ } synchronized (厕所门显示有人 ??) { // 上厕所任务 ........ }
而以下案例使用 Lock 接口来完成,同步锁机制,可以理解为:Lock是synchronized的升级版
Lock这种同步锁机制,是灵活的,是看得见的,什么时候锁住,什么时候释放锁,锁是什么锁??...... ,这个是看到的,例如:
// 定义一个锁?? private Lock lock = new ReentrantLock(); // ??锁定 锁住 lock.lock(); // 多线程/多地方调用 执行操作共享数据的代码 ....... // ??释放锁
把synchronized 修改成>>> Lock接口 的案例:
package android.java.thread19; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 售票线程 */ class Booking implements Runnable { /** * 模拟票的总算 10张票 - 共享数据 */ private int ticket = 10; /** * Lock是接口不是直接实例化,需要实例化Lock的实现类ReentrantLock,这样就创建了一把锁?? */ private Lock lock = new ReentrantLock(); @Override public void run() { while (true) { /** * 锁??定 操作共享数据的代码 * 只要锁定后 不管CPU如何疯狂的切换执行,只要同步代码块里面的代码没有执行完, * 就不准其他线程进来执行,这样就保证了多线程操作共享数据的安全新 */ lock.lock(); if (ticket > 0) { // 让线程在这里停一下,会更加容易复现线程的安全问题,就算不加这行代码,安全问题依然有 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("名称:" + Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票"); ticket--; } /** * 释放锁??,锁是资源 * 释放锁??后 就不再持有锁?? * 当不再持有锁??,其他然后线程都可以执行进入代码了 * * 注意?:一旦锁定后,就一旦要释放锁,否则所以线程都进不了锁定的代码 */ lock.unlock(); } } } /** * 售票案例 */ public class LockTestDemo { public static void main(String[] args) { /** * 定义Runnable实现类Booking,此实现类Booking不是线程,此实现类Booking给四个Thread去执行的 */ Runnable booking = new Booking(); // 实例化线程对象 Thread thread1 = new Thread(booking); // 此实现类Booking给Thread去执行的 Thread thread2 = new Thread(booking); // 此实现类Booking给Thread去执行的 Thread thread3 = new Thread(booking); // 此实现类Booking给Thread去执行的 Thread thread4 = new Thread(booking); // 此实现类Booking给Thread去执行的 // 开启启动线程 thread1.start(); // 启动第Thread-0窗口 执行卖票任务 thread2.start(); // 启动第Thread-1窗口 执行卖票任务 thread3.start(); // 启动第Thread-2窗口 执行卖票任务 thread4.start(); // 启动第Thread-3窗口 执行卖票任务 } }
执行结果: