Synchronized关键字的使用
1.使用static关键字修饰synchronized,将锁升级成类级别的锁,获得是相同的锁,可以保证一个对象对应的方法执行完以后再执行其余对象的方法。处理锁争用的问题。只是用synchronized得到的是不同的锁,他们互不影响。
2.synchronized的锁重入,可以是在获得锁后再次请求可以再次获得该对象的锁。
public class SyncDubbo1 {
public synchronized void method1(){
System.out.println("method1..");
method2();
}
public synchronized void method2(){
System.out.println("method2..");
method3();
}
public synchronized void method3(){
System.out.println("method3..");
}
static class Main {
public int i = 10;
public synchronized void operationSup(){
try {
i--;
System.out.println("Main print i = " + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Sub extends Main {
public synchronized void operationSub(){
try {
while(i > 0) {
i--;
System.out.println("Sub print i = " + i);
Thread.sleep(100);
this.operationSup();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.对于异常的处理分两种情况,一是原子性则要抛出异常,二是使用continue跳过。
4.synchronized代码块,优化代码执行时间,减小锁的粒度。
5.使用synchronized时需要注意到的问题
不要使用string常量加锁,会出现死循环问题
不要再代码块中修改锁中的对象,属性改变不影响。
死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况
synchronized只是一个内置锁的加锁机制,当某个方法加上synchronized关键字后,就表明要获得该内置锁才能执行,并不能阻止其他线程访问不需要获得该内置锁的方法。
6.三种使用方式
public void method1(){
synchronized (this) { //对象锁
try {
System.out.println("do method1..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void method2(){ //类锁
synchronized (ObjectLock.class) {
try {
System.out.println("do method2..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Object lock = new Object();
public void method3(){ //任何对象锁
synchronized (lock) {
try {
System.out.println("do method3..");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
7.synchronized的缺陷
当某个线程进入同步方法获得对象锁,那么其他线程访问这里对象的同步方法时,必须等待或者阻塞,这对高并发的系统是致命的,这很容易导致系统的崩溃。如果某个线程在同步方法里面发生了死循环,那么它就永远不会释放这个对象锁,那么其他线程就要永远的等待。这是一个致命的问题。