搬运文章
具体请看下面这位大佬的文章,写得真好
http://www.cnblogs.com/xrq730/p/4851350.html
一、线程访问不同的synchronized(this)
package java_lang_Object;
/**
* Created by luckyboy on 2018/7/7.
*/
public class SynchronizedTest_II {
public static void main(String[] args){
ThreadDomain1 threadDomain1 = new ThreadDomain1();
Mythread_1 mythread_1 = new Mythread_1(threadDomain1);
Mythread_2 mythread_2 = new Mythread_2(threadDomain1);
mythread_1.start();
mythread_2.start();
}
}
class ThreadDomain1{
public void methodA(){
//获得ThreadDomain1实例对象锁
synchronized (this){
System.out.println(Thread.currentThread().getName()+"进入了methodA的同步代码块");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休息了2s后退出methodA的同步代码块");
}
}
public void methodB(){
//获得ThreadDomain1实例对象锁
synchronized (this){
System.out.println(Thread.currentThread().getName()+"进入了methodB的同步代码块");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休息了2s后退出methodB的同步代码块");
}
}
}
//线程类1访问ThreadDomain1的methodA
class Mythread_1 extends Thread{
private ThreadDomain1 threadDomain1;
public Mythread_1(ThreadDomain1 threadDomain1){
this.threadDomain1 = threadDomain1;
}
@Override
public void run(){
this.threadDomain1.methodA();
}
}
//线程类2访问ThreadDomain1的methodB
class Mythread_2 extends Thread{
private ThreadDomain1 threadDomain1;
public Mythread_2(ThreadDomain1 threadDomain1){
this.threadDomain1 = threadDomain1;
}
@Override
public void run(){
this.threadDomain1.methodB();
}
}
输出结果
Thread-0进入了methodA的同步代码块
Thread-0休息了2s后退出methodA的同步代码块
Thread-1进入了methodB的同步代码块
Thread-1休息了2s后退出methodB的同步代码块
结果分析:我们看到Thread-0和Thread-1是有序的执行的,这是因为两个线程使用的是同一个对象,这个时候,一旦Thread-0进入了同步代码块,就会获得ThreadDomain的实例对象锁,Thread-1只能等待。
结论:对于一个synchronized(this)同步代码块,如果两个线程分别访问两个不同的synchronized(this),那么此时也是同步的。
二、线程访问同一个synchronized(this)
1、两个线程使用同一个对象
public class SynchronizedTest_II {
public static void main(String[] args){
ThreadDomain1 threadDomain1 = new ThreadDomain1();
Mythread_1 mythread_1 = new Mythread_1(threadDomain1);
Mythread_1 mythread_01 = new Mythread_1(threadDomain1);
mythread_1.start();
mythread_01.start();
}
}
输出结果
Thread-0进入了methodA的同步代码块
Thread-0休息了2s后退出methodA的同步代码块
Thread-1进入了methodA的同步代码块
Thread-1休息了2s后退出methodA的同步代码块
2、两个线程使用不同的对象
public class SynchronizedTest_II {
public static void main(String[] args){
ThreadDomain1 threadDomain1 = new ThreadDomain1();
Mythread_1 mythread_1 = new Mythread_1(threadDomain1);
ThreadDomain1 threadDomain2 = new ThreadDomain1();
Mythread_1 mythread_01 = new Mythread_1(threadDomain2);
mythread_1.start();
mythread_01.start();
}
}
输出结果
Thread-1进入了methodA的同步代码块
Thread-0进入了methodA的同步代码块
Thread-0休息了2s后退出methodA的同步代码块
Thread-1休息了2s后退出methodA的同步代码块
结论
- 如果两个线程使用同一个对象,两个线程访问同一个synchronized(this),那么每次只允许一个线程执行,线程同步
- 如果两个线程使用不同的对象,两个线程访问同一个synchronized(this),那么线程可以同时访问这个代码块,线程异步
二、synchronized方法和synchronized(this)
class ThreadDomain1{
public void methodA(){
synchronized (this){
System.out.println(Thread.currentThread().getName()+"进入了methodA的同步代码块");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休息了2s后退出methodA的同步代码块");
}
}
public synchronized void methodC(){
System.out.println(Thread.currentThread().getName()+"进入了methodC的同步方法");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休息了2s后退出methodC的同步方法");
}
}
//Mythread_1调用同步代码块synchronized(this)
class Mythread_1 extends Thread{
private ThreadDomain1 threadDomain1;
public Mythread_1(ThreadDomain1 threadDomain1){
this.threadDomain1 = threadDomain1;
}
@Override
public void run(){
this.threadDomain1.methodA();
}
}
//Mythread_3调用synchronized同步方法
class Mythread_3 extends Thread{
private ThreadDomain1 threadDomain1;
public Mythread_3(ThreadDomain1 threadDomain1){
this.threadDomain1 = threadDomain1;
}
@Override
public void run(){
this.threadDomain1.methodC();
}
}
1、测试代码:两个线程使用相同的对象,一个访问synchronized方法,一个访问synchronized(this){}
package java_lang_Object;
/**
* Created by luckyboy on 2018/7/7.
*/
public class SynchronizedTest_II {
public static void main(String[] args){
ThreadDomain1 threadDomain1 = new ThreadDomain1();
Mythread_1 mythread_1 = new Mythread_1(threadDomain1);
Mythread_3 mythread_3 = new Mythread_3(threadDomain);
mythread_1.start();
mythread_3.start();
}
}
输出结果
Thread-0进入了methodA的同步代码块
Thread-0休息了2s后退出methodA的同步代码块
Thread-1进入了methodC的同步方法
Thread-1休息了2s后退出methodC的同步方法
2、测试代码:两个线程使用不同的对象,一个访问synchronized方法,一个访问synchronized(this){}
package java_lang_Object;
/**
* Created by luckyboy on 2018/7/7.
*/
public class SynchronizedTest_II {
public static void main(String[] args){
ThreadDomain1 threadDomain1 = new ThreadDomain1();
Mythread_1 mythread_1 = new Mythread_1(threadDomain1);
ThreadDomain1 threadDomain2 = new ThreadDomain1();
Mythread_3 mythread_3 = new Mythread_3(threadDomain2);
mythread_1.start();
mythread_3.start();
}
}
输出结果
Thread-0进入了methodA的同步代码块
Thread-1进入了methodC的同步方法
Thread-0休息了2s后退出methodA的同步代码块
Thread-1休息了2s后退出methodC的同步方法
结论
- 如果两个线程使用同一个对象,一个访问synchronized方法,另一个访问synchronized(this){},那么两个线程是同步的。
- 如果两个线程使用不同的对象,一个访问synchronized方法,另一个访问synchronized(this){},那么两个线程是异步的
三、synchronized静态方法和synchronized(this){}
class ThreadDomain1{
public void methodA(){
synchronized (this){
System.out.println(Thread.currentThread().getName()+"进入了methodA的同步代码块");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休息了2s后退出methodA的同步代码块");
}
}
public synchronized static void methodD(){
System.out.println(Thread.currentThread().getName()+"进入了methodD的同步静态同步方法");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休息了2s后退出methodC的静态同步方法");
}
}
class Mythread_1 extends Thread{
private ThreadDomain1 threadDomain1;
public Mythread_1(ThreadDomain1 threadDomain1){
this.threadDomain1 = threadDomain1;
}
@Override
public void run(){
this.threadDomain1.methodA();
}
}
class Mythread_4 extends Thread{
/*private ThreadDomain1 threadDomain1;
public Mythread_4(ThreadDomain1 threadDomain1){
this.threadDomain1 = threadDomain1;
}*/
@Override
public void run(){
ThreadDomain1.methodD();
}
}
1、测试
package java_lang_Object;
/**
* Created by luckyboy on 2018/7/7.
*/
public class SynchronizedTest_II {
public static void main(String[] args){
ThreadDomain1 threadDomain1 = new ThreadDomain1();
Mythread_1 mythread_1 = new Mythread_1(threadDomain1);
Mythread_4 mythread_4 = new Mythread_4();
mythread_1.start();
mythread_4.start();
}
}
输出结果
Thread-0进入了methodA的同步代码块
Thread-1进入了methodD的同步静态同步方法
Thread-0休息了2s后退出methodA的同步代码块
Thread-1休息了2s后退出methodC的静态同步方法
结论
- 两个线程使用同一个对象(静态方法不需要使用对象),一个访问synchronized修饰的静态方法,另一个访问synchronized(this){},线程是不同步的,更不用说两个线程使用不同线程的情况
总结
- 如果两个线程一个访问synchronized修饰的静态方法,另一个访问synchronized(this){};那么两个线程是异步执行的
- 如果两个线程使用不同的对象的情况下,两个线程访问的是不同对象的方法,这个时候线程之间是异步的
- 如果两个线程使用相同的对象的情况下,两个线程不管是同时访问同一个synchronized(this){},还是同时访问synchronized()方法、或者是一个访问synchronized(this){} 而另一个访问synchronized();此时都会发生阻塞的情况