1. 线程的同步
- 在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性。
- 也可以这样理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作。
3. 同步具体方法–Synchronized
- 同步代码块
synchronized(对象){
}
synchronized还可以放在方法声明中,表示整个方法为同步方法
public synchronized void m(String name) {
}
- 如何理解:
就好像某小伙伴上厕所前先把门关上(上锁),完事后再出来(解锁),那么其它小伙伴就可在使用厕所了,如图:

4. 使用synchronized解决售票“超卖”的问题:
SellTicket03 sellTicket03 = new SellTicket03();
new Thread(sellTicket03).start();
new Thread(sellTicket03).start();
new Thread(sellTicket03).start();
class SellTicket03 implements Runnable {
private int ticketNum = 200;
private boolean loop = true;
public synchronized void sell() {
if (ticketNum <= 0) {
System.out.println("售票结束...");
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
+ " 剩余票数=" + (--ticketNum));
}
@Override
public void run() {
while (loop) {
sell();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36

- 使用
synchronized 同步,可以防止多个线程去操作同一段代码,造成售票“超卖”现象
5. 分析同步原理

6.1 基本介绍
- Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
- 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任意时刻,只能有一个线程访问该对象
- 关键字
synchronized来与对象的互斥锁联系,当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问 - 同步的局限性:导致程序的执行效率降低
- 同步方法(非静态的)的锁可以是
this,也可以是其他对象(要求是同一个对象)
- 上面的
public void synchronized sell() 方法是属于 非静态的同步方法,这时锁在 this 对象,可以使用 this 表示锁 - 代码块加锁和方法上加锁都是可以的
public void sell() {
synchronized (this) {
if (ticketNum <= 0) {
System.out.println("售票结束...");
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
+ " 剩余票数=" + (--ticketNum));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 非静态的同步方法或代码块的锁也可以是其他对象(要求是同一个对象,多个线程操作同一个对象),如:此时线程操作的对象 object 是同一个对象,所以可以使用 object 来表示锁
Object object = new Object();
synchronized (object) {
}
- 同步方法(静态的)的锁为当前类本身
同步方法(静态的)的锁为当前类本身
1. public synchronized static void m1() {} 锁是加在当前类 SellTicket03.class
public synchronized static void m1() {
}
2. 如果在静态方法中,实现一个同步代码块
public static void m2() {
synchronized (SellTicket03.class) {
System.out.println("m2");
}
}
6.2 注意事项和细节
- 同步方法如果没有使用
static修饰:默认锁对象为this - 如果方法使用
static修饰,默认锁对象:当前类.class - 实现的落地步骤:
- 需要先分析上锁的代码
- 选择 同步代码块(同步的范围小效率高)或 同步方法
- 要求多个线程的锁对象为同一个即可