多个线程访问同一个synchronized方法,只有一个线程能够进入该方法。如果多个线程访问一个对象不同的synchronized方法呢?还是只有一个能进入吗?
下面验证一下:
package volatile1;
import java.util.concurrent.CountDownLatch;
/**
* Created by sxb-gt on 2018/1/21.
* “主线程类”注意:该类并没有集成Thread。只是为了形象,才取的这个名字。
*/
public class MainThread2 {
private Integer i = 0;
public synchronized void syn1() {
System.out.println(Thread.currentThread().getName()+":" + "进入syn1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":" + "执行完syn1");
}
public synchronized void syn2() {
System.out.println(Thread.currentThread().getName()+":" + "进入syn2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":" + "执行完syn2");
}
public static void main(String[] args) {
MainThread2 mainThread = new MainThread2();
AssistantThread2 at2 = new AssistantThread2(mainThread);
AssistantThread3 at3 = new AssistantThread3(mainThread);
at2.start();
at3.start();
}
}
package volatile1;
import sun.applet.Main;
/**
* Created by sxb-gt on 2018/1/21.
*/
public class AssistantThread2 extends Thread{
private MainThread2 mainThread;
public AssistantThread2(MainThread2 mainThread) {
this.mainThread = mainThread;
}
@Override
public void run() {
mainThread.syn1();
}
}
package volatile1;
/**
* Created by sxb-gt on 2018/1/21.
*/
public class AssistantThread3 extends Thread{
private MainThread2 mainThread;
public AssistantThread3(MainThread2 mainThread) {
this.mainThread = mainThread;
}
@Override
public void run() {
mainThread.syn2();
}
}
执行结果:
Thread-0:进入syn1
Thread-0:执行完syn1
Thread-1:进入syn2
Thread-1:执行完syn2
总结:第二个线程是在第一个线程完全执行完之后才执行的。所以,方法上面加上synchronized锁住的是当前对象,所以同一时间只有一个线程能够访问对象中的其中一个synchronized方法。对于非synchronized方法,则没有限制。
接下来,调整下syn2去掉synchronized
public void syn2() {
System.out.println(Thread.currentThread().getName()+":" + "进入syn2");
System.out.println(Thread.currentThread().getName()+":" + "执行完syn2");
}
执行结果:
Thread-0:进入syn1
Thread-1:进入syn2
Thread-1:执行完syn2
Thread-0:执行完syn1
总结:非synchronized方法可以随意访问,不受限制。
那么同步代码块呢?如果一个线程先访问了synchronized方法,另一个线程可以访问同步代码块吗?接下来验证一下:
调整syn2方法如下:
public void syn2() {
System.out.println(Thread.currentThread().getName()+":" + "进入syn2");
synchronized (this) {
System.out.println("进入同步代码块");
}
System.out.println(Thread.currentThread().getName()+":" + "执行完syn2");
}
执行结果:
Thread-0:进入syn1
Thread-1:进入syn2
Thread-0:执行完syn1
进入同步代码块
Thread-1:执行完syn2
结论:可以看到输出结果中,只有syn1执行完后,才进入syn2。其实 这里要注意的是,synchronized括号里面的是this,代表的是这个对象。线程需要拿到对象的锁,才可以进入同步代码块。因此效果和同步方法类似。如果synchronized括号后面不写this效果会怎样呢?
调整syn2方法如下:
public void syn2() {
System.out.println(Thread.currentThread().getName()+":" + "进入syn2");
synchronized (i) {
System.out.println("进入同步代码块");
}
System.out.println(Thread.currentThread().getName()+":" + "执行完syn2");
}
执行结果:
Thread-0:进入syn1
Thread-1:进入syn2
进入同步代码块
Thread-1:执行完syn2
Thread-0:执行完syn1
总结:只要synchronized后面的括号中不是this,就可以进入同步代码块。