synchronized 线程同步的三种方法

时间:2022-05-18 13:04:56

通过一个简单的例子来了解synchronized:

使用五个线程,使共享变量 num 加1,最后得到结果 num = 5.

类count 实现add函数:

public static class count{
public int num=0;
public void add() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
num++; //实现加一
System.out.println(Thread.currentThread().getName()+
"-->"+num);
} //打印本次结果
}

线程:

public static class ThreadA extends Thread{
private count count;
public ThreadA(count count){
this.count=count;
}
public void run(){
count.add();
}
}

调用线程:

public static void main(String[] args) {
// TODO Auto-generated method stub
count count=new count();
for(int i=0;i<5;i++){
ThreadA thread = new ThreadA(count);
thread.start(); //调用函数

}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("the final num = "+ count.num);
} //打印最后结果


会出现如下结果:
T

hread-2-->3
Thread-0-->4
Thread-3-->3
Thread-1-->3
Thread-4-->3
the final num = 4

运行结果并不是期望得到的。

这是典型的线程不安全问题。使用synchronized 修饰add()完成对函数的互斥。

synchronized有三种不同写法 性能从低到优如下排列:

最差 同步方法体:

public static class count{
public int num=0;
public synchronized void add() { //同步方法
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
num++;
System.out.println(Thread.currentThread().getName()+
"-->"+num);
}
}



中等 同步块:

public static class count {
public int num = 0;
public void add() {
synchronized (this) { //同步块

try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
num++;
System.out.println(Thread.currentThread().getName() + "-->"
+ num);
}
}
}

最优 使用byte对象:

public static class count {
public int num = 0;
private byte [] lock=new byte[1];
public void add() {
synchronized (lock) { //使用的是lock 而不是this

try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
num++;
System.out.println(Thread.currentThread().getName() + "-->"
+ num);
}
}
}

因为锁的是对象,加锁和释放锁都需要此对象的资源,所有使用一个字节的byte是最优的结果。

使用以上三种方法都可实现以下效果:

Thread-0-->1
Thread-3-->2
Thread-4-->3
Thread-2-->4
Thread-1-->5
the final num = 5