程序1:
package testsynchronized;
public class Thread1 implements Runnable {
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ " synchronized loop " + i);
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}
输出:
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
A synchronized loop 5
A synchronized loop 6
A synchronized loop 7
A synchronized loop 8
A synchronized loop 9
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
B synchronized loop 5
B synchronized loop 6
B synchronized loop 7
B synchronized loop 8
B synchronized loop 9
因为a先运行,b后运行,所以a先输出,b后输出,而且不会出现a和b并发输出,因为a已经获得了Thread1的对象锁。
程序2:
package testsynchronized;
public class Thread2 {
public void m1() {
synchronized (this) {
int i = 10;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {
}
}
}
}
public void m2() {
int i = 10;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread(new Runnable() {
public void run() {
myt2.m1();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
myt2.m2();
}
}, "t2");
t1.start();
t2.start();
}
}
输出:
t2 : 9
t1 : 9
t2 : 8
t2 : 7
t2 : 6
t1 : 8
t2 : 5
t2 : 4
t1 : 7
t2 : 3
t2 : 2
t2 : 1
t2 : 0
t1 : 6
t1 : 5
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
这个输出不唯一。
可以看出,当一个线程运行同步代码块时,另一个线程可以同时运行非同步代码块。
程序3:
package testsynchronized;
public class Thread3 {
public void m1() {
synchronized (this) {
int i = 10;
while (i-- > 0) {
System.out
.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m2() {
synchronized (this) {
int i = 10;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
Thread t1 = new Thread(new Runnable() {
public void run() {
myt3.m1();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
myt3.m2();
}
}, "t2");
t1.start();
t2.start();
}
}
输出:
t1 : 9
t1 : 8
t1 : 7
t1 : 6
t1 : 5
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 9
t2 : 8
t2 : 7
t2 : 6
t2 : 5
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
可以看出,当一个线程运行同步代码块时,另一个线程不能同时运行同步代码块。
程序4:
package testsynchronized;
public class Thread4 {
public void m1() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {
}
}
}
}
public synchronized void m2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
final Thread4 myt4 = new Thread4();
Thread t1 = new Thread(new Runnable() {
public void run() {
myt4.m1();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
myt4.m2();
}
}, "t2");
t1.start();
t2.start();
}
}
输出:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
可以看出,当一个线程运行同步代码块时,另一个线程就不能同时运行同步方法。
程序5:
package testsynchronized;
public class Thread5 {
class Inner {
private void m1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
private void m2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
private void m1(Inner inner) {
synchronized (inner) { // 使用对象锁
inner.m1();
}
}
private void m2(Inner inner) {
inner.m2();
}
public static void main(String[] args) {
final Thread5 myt5 = new Thread5();
final Inner inner = myt5.new Inner();
Thread t1 = new Thread(new Runnable() {
public void run() {
myt5.m1(inner);
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
myt5.m2(inner);
}
}, "t2");
t1.start();
t2.start();
}
}
输出:
t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0
可以看到,当使用同步代码块时,并非要this,其他对象也可以,而且另一个线程可以同时运行飞同步代码块。
总结
使用synchronized就相当于取得了某个锁,如果是多线程,最多只有一个线程能运行同步方法,但是对于非同步方法,其他线程也能同时运行。
对于下面的代码:
package testsynchronized;
public class Thread6 {
private boolean a;
private boolean b;
public void setA(boolean a) {
this.a = a;
}
public void setB(boolean b) {
this.b = b;
}
public synchronized void setSA(boolean a) {
this.a = a;
}
public synchronized void setSB(boolean b) {
this.b = b;
}
public void setAB() {
setSA(true);
setSB(false);
}
public synchronized void setSAB() {
setA(false);
setB(true);
}
public void check() {
System.out.println(a == b);
}
/**
* @param args
*/
public static void main(String[] args) {
final Thread6 myt6 = new Thread6();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
myt6.setSAB();
myt6.check();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
myt6.setA(true);
myt6.setB(true);
}
}, "t2");
t1.start();
t2.start();
}
}
是否会输出true。
理论上是有可能输出true的,因为两个线程,分别调用同步方法和非同步方法。为了输出true,可以加些代码:
public static void main(String[] args) {
final Thread6 myt6 = new Thread6();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
myt6.setSAB();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
myt6.check();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
myt6.setA(true);
myt6.setB(true);
}
}, "t2");
t1.start();
t2.start();
}
这样就输出true了。