多线程卖票同步代码
多线程虽然提高了效率,但也引发了一些问题,举个经典的栗子
1 public class SellTicketsDemo implements Runnable { 2 private static int ticketNum=10; 3 4 @SneakyThrows 5 @Override 6 public void run() { 7 sell(); 8 } 9 10 public void sell() throws InterruptedException { 11 Thread.sleep(1000);//等待是为了模拟出并发导致的问题 12 if(ticketNum>0){ 13 System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum+"张票"); 14 ticketNum--; 15 } 16 } 17 18 public static void main(String[] args) { 19 for (int i = 0; i <21 ; i++) { 20 new Thread(new SellTicketsDemo()).start(); 21 } 22 }
执行后会出现多个线程拿到了同一张票,这样不行,这时就需要同步代码,同步代码有多种方式
1.关键字加到静态方法上,因为class对象在项目启动时,就在堆中生成,并且唯一,所以可以锁住,如果添加到非静态方法上,就需要使用同步代码块
1 public static synchronized void sell() throws InterruptedException {//用于静态方法,锁是当前class对象,也就是SellTicketsDemo类对应的class对象 2 Thread.sleep(1000);//等待是为了模拟出并发导致的问题 3 if(ticketNum>0){ 4 System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum+"张票"); 5 ticketNum--; 6 } 7 }
2.同步代码块
1 private static Object lock=new Object(); 2 public static void sell() throws InterruptedException { 3 synchronized(lock) { 4 Thread.sleep(1000);//等待是为了模拟出并发导致的问题 5 if (ticketNum > 0) { 6 System.out.println(Thread.currentThread().getName() + "买了第" + ticketNum + "张票"); 7 ticketNum--; 8 } 9 } 10 }
3.Lock锁
1 private static Lock lock = new ReentrantLock(); 2 public static void sell() throws InterruptedException { 3 lock.lock(); 4 try { 5 Thread.sleep(1000);//等待是为了模拟出并发导致的问题 6 if (ticketNum > 0) { 7 System.out.println(Thread.currentThread().getName() + "买了第" + ticketNum + "张票"); 8 ticketNum--; 9 } 10 }catch (Exception e){ 11 e.getMessage(); 12 }finally { 13 lock.unlock(); 14 } 15 }
当然,这些了解就行了,现在都分布式了,分布式锁才是正道