一、对象锁
synchronized关键字修饰普通方法或者方法中代码块。防止多线程中同一个实例同时访问该对象的方法。锁的是实例对象。
创建一个TestSynchronized类,syncA()方法。
public class TestSynchronized {
//1对象锁
public void syncA() {
String threadName = Thread.currentThread().getName();
synchronized (this) {
Log.d(TAG, threadName + "线程, start syncA()方法。");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
Log.d(TAG, threadName + "线程, end syncA()方法。");
}
}
}
启动两个线程,创建两个对象,执行syncA方法。
new Thread(new Runnable() {
public void run() {
new TestSynchronized().syncA();
}
}).start();
new Thread(new Runnable() {
public void run() {
new TestSynchronized().syncA();
}
}).start();
线程运行syncA方法时,并未因为synchronized同步竞争锁导致休眠,因为加锁的是各自的对象,不是类。synchronized关键字可以直接修饰syncA方法,如果改一下代码。
final TestSynchronized sro = new TestSynchronized();
new Thread(new Runnable() {
public void run() {
sro.syncA();
}
}).start();
new Thread(new Runnable() {
public void run() {
sro.syncA();
}
}).start();
一个对象,两个线程并发调用syncA()方法,竞争锁休眠,锁就是创建的对象本身。
增加一个synchronized关键字修饰的方法syncB(),第二个线程执行syncB()方法。
//2对象锁
public synchronized void syncB() {
String threadName = Thread.currentThread().getName();
Log.d(TAG, threadName + "线程, start syncA()方法。");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
Log.d(TAG, threadName + "线程, end syncA()方法。");
}
同一个对象,两个线程,执行syncA()和syncB()方法,竞争锁休眠。
实例对象被lock,只能有一个线程进入该对象某个synchronized方法的代码块,其他线程无法进入任何synchronized同步方法。
同步代码块和同步方法,同步方法默认以当前对象作为锁,静态方法以当前class作为锁。同步代码块是可能引起线程问题的一段代码,而不是整个方法,可以选择锁的内容。
普通对象锁,不同对象,可同时访问。相同对象,不同加锁代码,不可同时访问。
二、静态锁
synchronized关键字修饰的静态方法或代码块锁是class类型,防止多线程中多个对象或类同时访问该类中的synchronized static方法,锁的是类对象。
public class TestSynchronized {
//1对象锁
public void syncA() {
String threadName = Thread.currentThread().getName();
synchronized (TestSynchronized.class) {
Log.d(TAG, threadName + "线程, start syncA()方法。");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
Log.d(TAG, threadName + "线程, end syncA()方法。");
}
}
}
将syncA()加上static关键字,静态方法,或者synchronized代码块将this改成TestSynchronized.class,创建两个对象,两个线程并发,执行syncA()方法,因为加的锁是类,两个方法会竞争锁。
new Thread(new Runnable() {
public void run() {
new TestSynchronized().syncStaticA();
}
}).start();
new Thread(new Runnable() {
public void run() {
TestSynchronized.syncStaticB();
}
}).start();
两个线程,一个是对象执行同步静态syncStaticA()方法,一个是类执行同步静态syncStaticB()方法,加类锁,线程会竞争锁。
如果类对象被lock,只能有一个线程进入该类某个synchronized方法的代码块,其他线程无法进入任何synchronized同步方法。
静态锁,不同对象,相同方法及不同加锁代码块,都不能同时访问。
普通锁和类锁两种不同类型的锁,他们之间并发时不会相互产生竞争,比如一个类两个方法分别上对象锁和类锁,创建两个对象,分别执行两个方法时,锁不同,不会产生竞争。
任重而道远
网友评论