线程同步
-
案例:三个窗口卖100张票
//定义一个类SellTicket实现Runnable接口,定义成员变量100张票 public class SellTicket implements Runnable{ private int tickets = 100; //重写run方法 @Override public void run(){ while (true){ //没有票后,死循环一直让动作执行 if(tickets>0){ //判断票数大于1卖票 System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票"); //告知卖票窗口 tickets--; //卖票后总数减一 } } } } //创建测试类 public class SellTicketDemo{ public static void main(String[] args){ //创建SellTicket类对象 SellTicket st = new SellTicket(); //创建三个Thread类对象,把SellTicket对象作为构造方法的参数,给出对应窗口名称 Thread t1 = new Thread(st,"窗口1"); Thread t2 = new Thread(st,"窗口2"); Thread t3 = new Thread(st,"窗口3"); //启动线程 t1.start(); t2.start(); t3.start(); } }
-
多线程程序出现安全问题(条件:多线程环境;有共享数据;有多条语句操作共享数据)
-
避免安全问题,需要锁多条语句操作共享数据,可以使用同步代码块实现(线程过多时耗费资源)
格式:synchronized(任意对象){多条语句操作共享数据的代码}(相当于给代码加锁,任意对象可以看成是一把锁)
public class SellTicket implements Runnable{ private int tickets = 100; private Object obj = new Object();//创建一个Object对象,当作同一把锁 @Override public void run(){ while (true){ synchronized(obj){ //当t1进来后,就会锁住代码,其他线程进不来 if(tickets>0){ try{Thread.sleep(100);}//休息100毫秒 catch(InterruptedException e){e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票"); tickets--; } } } } }
-
同步方法: 同步方法:就是把synchronized关键字加到方法上 格式:修饰符 synchronized返回值类型 方法名(方法参数){}
同步方法锁对象是 :this synchronized(this)
同步静态方法:把synchronized关键字加到静态方法上 格式:修饰符 static synchronized 返回值类型 方法名(方法参数){}
同步静态方法锁对象是:类名.class synchronized(SellTicket.class)
-
Lock锁实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
Lock中提供了获得锁和释放锁的方法:void lock():获得锁 void unlock():释放锁
Lock是接口不能直接实例化,采用实现类ReentranctLock来实例化 ReentrantLock的构造方法:ReentrantLock():创建一个ReentrantLock实例
public class SellTicket implements Runnable{ private int tickets = 100; private Lock lock = new ReentrantLock();//创建一个ReentrantLock实例化对象 @Override public void run(){ while (true){ try{ lock.lock(); if(tickets>0){ try{Thread.sleep(100);}//休息100毫秒 catch(InterruptedException e){e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票"); tickets--; } finally{lock.unlock();}//释放锁不管上面代码是否出现错误都执行 } } } }