使用synchronized同步方法和同步代码块,当是两个线程调用同一对象里面的synchronized方法或者代码块时,或者另外不是synchronized方法的时候,会是什么情况呢?
public class Orange {
private int numOne=10;
private int numtwo=10;
public synchronized void test1() {
while(numOne>0) {
System.out.println("我是方法test1的numOne:"+numOne--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void test2() {
while(numtwo>0) {
System.out.println("我是方法test2的numtwo:"+numtwo--);
}
}
}
public class Run1 implements Runnable{
private Orange orange;
public Run1(Orange orange) {
this.orange=orange;
}
@Override
public void run() {
orange.test1();
}
}
public class Run2 implements Runnable{
private Orange orange;
public Run2(Orange orange) {
this.orange=orange;
}
@Override
public void run() {
orange.test2();
}
}
public static void main(String[] args){
Orange orange = new Orange();
new Thread(new Run1(orange)).start();
new Thread(new Run2(orange)).start();
}
输出:
我是方法test1的numOne:10
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
由上分析,在test1方法中sleep了1000毫秒,但是另外一个线程仍旧不去执行test2方法,
两个线程共用一个Orange对象,因此可以知道,当有不同线程调用同一对象的synchronized同步方法时,另外一个线程调用同一对象的其他synchronized同步方法时,会进入阻塞状态,既第一个线程首先获得了对象锁,因而另外一个线程无法取得该对象锁,从而进入阻塞状态。
如果同步代码块会怎么样呢?把Orange类的test2方法改成同步代码块,其他代码不变。
public class Orange {
private int numOne=10;
private int numtwo=10;
Fruit fruit=new Fruit();
public synchronized void test1() {
while(numOne>0) {
System.out.println("我是方法test1的numOne:"+numOne--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void test2() {
synchronized (this) {
while (numtwo>0) {
System.out.println("我是方法test2的numtwo:"+numtwo--);
}
}
}
}
输出:
我是方法test1的numOne:10
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
通过观察输出,发现跟上面的输出是一样的,从而知道synchronized(this)也是获得同一对象锁的,this指向当前对象,因而是同一个对象,如果把synchronized(this)里面的this改成其他对象呢?又会怎么样?
package com.qrj.bean;
public class Orange {
private int numOne=10;
private int numtwo=10;
String strObj=new String();
public synchronized void test1() {
while(numOne>0) {
System.out.println("我是方法test1的numOne:"+numOne--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void test2() {
synchronized (strObj) {
while (numtwo>0) {
System.out.println("我是方法test2的numtwo:"+numtwo--);
}
}
}
}
输出:
我是方法test1的numOne:10
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
通过观察输出,第一个线程首先执行了一次test1方法循环,然后sleep(1000),但仍旧持有该对象锁,但是从输出发现,这时候第二个线程执行了test2方法,而test2的同步代码块是synchronized(strObj),不再是this了,因而没有阻塞,就可以干点别的事情了。
那另外的线程可不可以执行同一对象的其他没有同步的方法而不进入不阻塞状态呢?把test2方法的同步代码块改一下,其他代码不变。
public void test2() {
while (numtwo>0) {
System.out.println("我是方法test2的numtwo:"+numtwo--);
}
}
输出:
我是方法test1的numOne:10
我是方法test2的numtwo:10
我是方法test2的numtwo:9
我是方法test2的numtwo:8
我是方法test2的numtwo:7
我是方法test2的numtwo:6
我是方法test2的numtwo:5
我是方法test2的numtwo:4
我是方法test2的numtwo:3
我是方法test2的numtwo:2
我是方法test2的numtwo:1
我是方法test1的numOne:9
我是方法test1的numOne:8
我是方法test1的numOne:7
我是方法test1的numOne:6
我是方法test1的numOne:5
我是方法test1的numOne:4
我是方法test1的numOne:3
我是方法test1的numOne:2
我是方法test1的numOne:1
通过输出知道,另外的线程可以执行同一对象的没有同步(synchronized)的方法而不进入阻塞状态,不用等待第一个线程执行的同步方法结束后才执行。
如有不正之处,还望多多指正~