synchronized的用法:站在对象锁和类锁的角度分析
对象锁和类锁的区别:
public class SynchronizedClass {
public synchronized void method(){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"我是对象锁");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void method1(){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"我是对象锁1");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static synchronized void method2(){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"我是类锁");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void method3(){
synchronized (SynchronizedClass.class) {
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"我是类锁1");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
SynchronizedClass synchronizedClass = new SynchronizedClass();
SynchronizedClass synchronizedClass1 = new SynchronizedClass();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedClass.method();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedClass.method1(); //同一对象执行结果同步
// synchronizedClass1.method1(); //不同对象执行结果异步
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedClass.method2(); //类锁和对象锁异步
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedClass.method3();
}
}).start();
}
}
1)多个线程访问同一对象的的同步代码时,只有一个线程能获取对象锁,其他的线程不能访问这个对象任何地方使用synchronized 修饰的代码必须等待或者阻塞,直到前面的线程释放锁,其他线程才能重新竞争锁。
2)多个线程访问不同对象的同步代码时,是互不干扰的,代码会异步执行
3)对象锁和类锁是互不干扰的,代码会异步执行
对象锁,锁的是类的对象实例。
写法有两种:
1)直接修饰方法
public synchronized void method(){
System.out.println("我是对象锁");
}
2)修饰代码块
public void method(){
//dosomething 业务代码
synchronized(this){
System.out.println("我是对象锁");
}//一个线程访问该对象的这个方法时候,另一个线程可以同时执行这个对象这个方法没用synchronized的代码
}
两种写法都是对象锁,一个是锁整个方法,一个是锁方法中的一部分代码,当一个线程访问一个对象的同步代码时候,其他线程访问同一个对象的其他没用synchronized修饰的方法或方法中的代码时,会异步执行。
类锁 ,一个抽象出来的概念,锁的是每个类的的Class对象,每个类的的Class对象在一个虚拟机中只有一个,所以类锁也只有一个。规则和对象锁一致
写法有两种:
1)静态方法
public static synchronized void method(){
System.out.println("我是类锁");
}
2)
public void method(){
synchronized (类名.class) {
System.out.println("我是第二种类锁");
}
}