每个对象都有一个标志锁。当对象的一个线程访问了对象的某个synchronized数据(包括函数)时,这个对象就将被“上锁”,被声明为synchronized的数据(包括函数)都不能被调用(因为当前线程取走了对象的“锁标志”)。
只有当前线程访问完它要访问的synchronized数据,释放“锁标志”后,同一个对象的其它线程才能访问synchronized数据。
注意:每个class也有一个“锁标志”。对于synchronized static数据(包括函数)可以在整个class下进行锁定,避免static数据的同时访问。
- 样例的场景
我们的业务需要获取一个序列号。下面是一个取得序列号的单例模式的例子,利用 synchronized 对get()函数进行约束,避免产生两个相同的序列号。
- 利用synchronized实现资源同步的java源代码
package com.thread;
/**
* 利用synchronized 避免多线程获取重复序列号
* @author 范芳铭
*/
public class EasySynchronizedGetSeq extends Thread {
private static int number = 0;
private static EasySynchronizedGetSeq seq = new EasySynchronizedGetSeq();
public EasySynchronizedGetSeq(String name){
super(name);
}
private EasySynchronizedGetSeq() {
}
public EasySynchronizedGetSeq getInstance() {
return seq;
}
public synchronized int get() {
number++; // (a)
return number;// (b)
}
public void run(){
for (int i = 0 ; i < 10; i ++){
int a = getInstance().get();// (1)
System.out.println(Thread.currentThread().getName() + ":" + a);
//模拟访问停顿
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//简单模拟多线程调用
EasySynchronizedGetSeq sepA = new EasySynchronizedGetSeq("A");
sepA.start();
EasySynchronizedGetSeq sepB = new EasySynchronizedGetSeq("---B");
sepB.start();
EasySynchronizedGetSeq sepC = new EasySynchronizedGetSeq("======C");
sepC.start();
}
}
运行结果
A:1
—B:2
======C:3
A:4
—B:6
======C:5
—B:7
A:8
======C:9
A:11
======C:12
—B:10
======C:13
—B:15
A:14
—B:16
A:18
======C:17
A:20
—B:21
======C:19
—B:23
A:24
======C:22
—B:25
A:27
======C:26
A:29
—B:30
======C:28
要证明错误很容易,只要有一个反例;但是要证明对很不容易,这个需要一整套的逻辑和支撑。
因此,这个结论,只是一个大概的结论。
时间: 2024-10-08 02:42:56