一. 同步
同步,就是加锁,避免同一个资源访问时会出现的问题。
还是以以前的卖票程序进行举例。
一.一 这是不加同步的
public static void main(String[] args) { test5(); } public static void test5(){ //实例化一次对象 MyRunnableDemo5 myRunnableDemo1=new MyRunnableDemo5(); Thread thread1=new Thread(myRunnableDemo1); Thread thread2=new Thread(myRunnableDemo1); Thread thread3=new Thread(myRunnableDemo1); //启动, 三个客户端进行抢票 thread1.start(); thread2.start(); thread3.start(); } static class MyRunnableDemo5 implements Runnable{ private int ticket=5; @Override public void run() { for(int i=0;i<10;i++){ if(ticket>0){ //加上一个延时,表示卖票需要耗费时间差。 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("还剩下:"+ticket+"张票"); ticket--; } } } }
运行程序, 观察控制台, 可能的一种结果
发现,查询的票数是不对的,并且卖出的票数也是不对的。
一.二 加入同步
同步,可以分为两种,一种是同步代码块, 另外一种是同步方法, 用 synchronized 关键字进行修饰。
一.二.一 同步代码块
public static void main(String[] args) { //test5(); test6(); } public static void test6(){ //实例化两次 MyRunnableDemo6 myRunnableDemo1=new MyRunnableDemo6(); Thread thread1=new Thread(myRunnableDemo1); Thread thread2=new Thread(myRunnableDemo1); Thread thread3=new Thread(myRunnableDemo1); //启动 thread1.start(); thread2.start(); thread3.start(); } static class MyRunnableDemo6 implements Runnable{ private int ticket=5; @Override public void run() { for(int i=0;i<10;i++){ // 进行同步, 同步的是当前对象 synchronized (this){ if(ticket>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("还剩下:"+ticket+"张票"); ticket--; } } } } }
运行程序,控制台打印输出
查询的票数是对的,卖出的票数也是对的。
一.二.二 同步方法
public static void main(String[] args) { //test5(); // test6(); test7(); } public static void test7(){ //实例化两次 MyRunnableDemo7 myRunnableDemo1=new MyRunnableDemo7(); Thread thread1=new Thread(myRunnableDemo1); Thread thread2=new Thread(myRunnableDemo1); Thread thread3=new Thread(myRunnableDemo1); //启动 thread1.start(); thread2.start(); thread3.start(); } static class MyRunnableDemo7 implements Runnable{ private int ticket=5; @Override public void run() { //调用同步方法 pay(); } //同步方法 public synchronized void pay(){ for(int i=0;i<10;i++){ if(ticket>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("还剩下:"+ticket+"张票"); ticket--; } } } }
运行程序,查看控制台信息