- Java在Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
- 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
- 关键字synchronized来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问
- 同步的局限性:导致程序的执行效率要降低
- 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)
- 同步方法(静态的)的锁为当前类本身
注意事项:
- 同步方法如果没有使用static修饰:默认锁对象为this
- 如果方法使用static修饰,默认锁对象:当前类.class
- 实现的落地步骤:
- 需要先分析上锁的代码
- 选择同步代码块或同步方法
- 要求多个线程的锁对象为同一个即可!
package test;public class Main { public static void main(String[] args) { //测试 SellTicket sellTicket = new SellTicket(); new Thread(sellTicket).start();//第1个线程-窗口 new Thread(sellTicket).start();//第2个线程-窗口 new Thread(sellTicket).start();//第3个线程-窗口 }}//实现接口方式, 使用synchronized实现线程同步class SellTicket implements Runnable { private int ticketNum = 100;//让多个线程共享 ticketNum private boolean loop = true;//控制run方法变量 Object object = new Object(); //同步方法(静态的)的锁为当前类本身 //1. public synchronized static void m1() {} 锁是加在 SellTicket.class //2. 如果在静态方法中,实现一个同步代码块. /* synchronized (SellTicket.class) { System.out.println("m2"); } */ public synchronized static void m1() { } public static void m2() { synchronized (SellTicket.class) { System.out.println("m2"); } } //1. public synchronized void sell() {} 就是一个同步方法 //2. 这时锁在 this对象 //3. 也可以在代码块上写 synchronize ,同步代码块, 互斥锁还是在this对象 public /*synchronized*/ void sell() { //同步方法, 在同一时刻, 只能有一个线程来执行sell方法 synchronized (/*this*/ object) { if (ticketNum <= 0) { System.out.println("售票结束..."); loop = false; return; } //休眠50毫秒, 模拟 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum));//1 - 0 - -1 - -2 } } @Override public void run() { while (loop) { sell();//sell方法是一个同步方法 } }}
