public class CountA {
private byte[] lock=new byte[1];
public synchronized void synchronizedA() throws InterruptedException {
while (true){
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+":同步任务A");
}
}
public void synchronizedB() throws InterruptedException {
synchronized (lock) {
while (true){
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+":同步任务B");
}
}
}
public void normalC(){
System.out.println(Thread.currentThread().getName()+":非同步任务C");
}
public class ThreadSynchronizedA implements Runnable {
private CountA count;
public ThreadSynchronizedA(CountA count) {
this.count = count;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
count.normalC();
}
public class ThreadSynchronizedB implements Runnable {
private CountA count;
public ThreadSynchronizedB(CountA count) {
this.count = count;
}
@Override
public void run() {
try {
count.synchronizedA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public class ThreadSynchronizedC implements Runnable {
private CountA count;
public ThreadSynchronizedC(CountA count) {
this.count = count;
}
@Override
public void run() {
try {
count.synchronizedB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
将上面 CountA 中的synchronizedB方法改为同步方法或者改为synchronized(this)代码块。
- 当一个线程访问 object 的一个synchonized(this)同步代码块时,另一个线程可以访问该 object 的非synchonized(this)同步代码块。
代码示例:
CountA countA = new CountA();
ThreadSynchronizedA tsA = new ThreadSynchronizedA(countA);
ThreadSynchronizedB tsB = new ThreadSynchronizedB(countA);
ThreadSynchronizedC tsC = new ThreadSynchronizedC(countA);
Thread t1 = new Thread(tsA, "线程tsA”);//非同步方法 Thread t2 = new Thread(tsB, "线程tsB”);//同步方法
t2.start();
Thread.sleep(10000);//为了让B线程先开始执行
t1.start();
执行以上程序,会发现在同步方法执行时,没有加 synchonized 的方法也可以执行。
- 当一个线程访问 object 的一个synchonized(this)同步代码块时,其他线程对 object 中所有其他synchonized(this)同步代码块 的访问被阻塞。
代码示例:
CountA countA = new CountA();
ThreadSynchronizedB tsB = new ThreadSynchronizedB(countA);
ThreadSynchronizedC tsC = new ThreadSynchronizedC(countA);
Thread t1 = new Thread(tsC, "线程tsC”);//同步方法 Thread t2 = new Thread(tsB, "线程tsB”);//同步方法
t2.start();
Thread.sleep(10000);
t1.start();
执行以上代码,发现始终运行线程 tsB。
保持 CountA 的代码如上
– 如果线程获取的不是 object 对象的锁,那么不会阻塞该 object 的其他synchonized(this)同步代码块 的访问。
示例代码:
CountA countA = new CountA();
ThreadSynchronizedB tsB = new ThreadSynchronizedB(countA);
ThreadSynchronizedC tsC = new ThreadSynchronizedC(countA);
Thread t1 = new Thread(tsC, "线程tsC");
Thread t2 = new Thread(tsB, "线程tsB");
t2.start();
Thread.sleep(10000);
t1.start();
执行代码,发现线程 tsC和 tsB 的方法都会执行,所以这种方式是非线程安全的。
同步代码的性能比较,从差到优如下:
同步方法体:
public synchonized void syncMethod(){
...
}
public int syncMethod(){
synchonized(this){
...
}
}
在方法上加锁的,获得锁进入方法后,还需要分配资源花费一定的时间。
private byte[] lock=new byte[1];
public int syncMethod(){
synchonized(lock){
...
}
}
锁是对象,而加锁和释放锁都需要此对象资源,那么锁对象肯定越小越好。