版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wueryan/article/details/86501041
synchronized的三种应用方式
(1)修饰实例方法
(2)修饰静态方法
(3)修饰代码块
修饰实例方法
/***
* 代码1-1
*/
public class SynDemo implements Runnable{
static int i=0;
public synchronized void increase(){
i++;
}
public void run(){
for(int j=0;j<1000000;j++){
this.increase();
}
}
public static void main(String[] args){
SynDemo demo = new SynDemo();
Thread t1 = new Thread(demo);
Thread t2 = new Thread(demo);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
在代码1-1中,我们开启了两个线程对全局变量i进行了加1的操作。在这个过程中,为了保证线程安全,由于我们对实例方法increase()进行了synchronized的修饰。此时线程会对对象锁进行竞争获取,先获取到锁的线程禁止其他线程调用increase()方法。
对于同一个对象来说,只有一个锁,一旦被某个线程竞争获取到锁了,其他线程就无法获取该对象的锁了。值得注意的是,同一个类的实例化对象如果是不同的,比如以下代码1-2的例子,那么对于线程来说,其实是获取了不同的对象锁,自然而然的对于increase()就会分别执行。
/***
* 代码1-2
*/
public class SynDemo implements Runnable{
static int i=0;
public synchronized void increase(){
i++;
}
public void run(){
for(int j=0;j<1000000;j++){
this.increase();
}
}
public static void main(String[] args){
SynDemo demo1 = new SynDemo();
SynDemo demo2 = new SynDemo();
Thread t1 = new Thread(demo1);
Thread t2 = new Thread(demo2);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
修饰静态方法
public class synDemo2 implements Runnable{
static int i =0 ;
public static synchronized void increase(){
i++;
}
public synchronized void increase2(){
i++;
}
public void run(){
for (int j=0;j<1000000;j++){
increase();
}
}
public static void main(String[] args){
SynDemo2 demo1 = new SynDemo2();
SynDemo2 demo2 = new SynDemo2();
Thread t1 = new Thread(demo1);
Thread t2 = new Thread(demo2);
t1.start();
t2.start();
t1.join();
t2.join();
}
}
修饰静态方法时,此时会锁当前类的class对象锁。这里值得注意的时,类的锁和实例对象的锁并不是同一个锁。因此在demo中,我们可以看到同样是用synchronized修饰increase()和increase2()方法,但是由于实例的锁和类的class对象锁并不会产生互斥。这里在不同线程进行操作时,可能会产生线程安全问题。
synchronized同步代码块
public class SynDemo3 implements Runnable{
static SynDemo3 instance = new SynDemo3();
static int i=0;
public void run(){
synchronized(instance){
for(int j=0;j<1000000;j++){
i++;
}
}
synchronized(this){
//do something
}
synchronized(SynDemo3.class){
//do something
}
}
}
除了instance作为对象外,还可以用this对象或者当前类的class对象作为锁。