java thread 线程中 的synchronized关键字 可以放到方法上,也可以修饰对象上
eg:
private synchronized void testSyncMethod() {
//当线程执行到此处时,它必须获得一个锁,此时锁定的对象是:调用此方法的对象a
}
private void testSyncMethod() {
synchronized(this){
//当线程执行到此处时,它必须获得一个锁,此时锁定的对象是:调用此方法的对象a
}
}
synchronized 可以修饰任何对象(int 等基本类型不在范围内),当然也包括类对象A.class
eg:
class A {
private static synchronized void testSyncMethod() {
//此时当前线程获得的锁是:A.class
}
private void testSyncMethod(){
synchronized(A.class){
//此时当前线程获得的锁是:A.class
}
}
}
既然A.class ,对象a 不是同一对象,即synchronized 修饰普通方法和静态方法是锁定了不同的对象。
下面的代码示例:
package com.horizon.thread.classLock;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* synchronized 修饰 static方法 锁定的是 class对象
* 即:synchronized (RunnableTest.class)
* @author wangxinchun
*
*/
public class SynchronizedStatic implements Runnable {
private static boolean flag = true;
private static synchronized void testSyncMethod() { // 注意static修饰的同步方法,监视器:SynchronizedStatic.class
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testSyncMethod:" + i);
}
}
private void testSyncBlock() {
synchronized (SynchronizedStatic.class) { // 显示使用获取class做为监视器.它与static synchronized method隐式获取class监视器一样.
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testSyncBlock:" + i);
}
}
}
public void run() {
// flag是static的变量.所以,不同的线程会执行不同的方法,只有这样才能看到不同的锁定效果.
if (flag) {
flag = false;
testSyncMethod();
} else {
flag = true;
testSyncBlock();
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(2);
SynchronizedStatic rt = new SynchronizedStatic();
SynchronizedStatic rt1 = new SynchronizedStatic();
exec.execute(rt);
exec.execute(rt1);
exec.shutdown();
}
}
以上代码输出的结果是一个线程先执行,然后另外一个线程执行,输出是有序的:
testSyncMethod:0
testSyncMethod:1
testSyncMethod:2
testSyncMethod:3
testSyncMethod:4
testSyncMethod:5
如果去掉testSyncMethod 的静态方法,两个线程输出结果将是混乱在一起的(线程不再锁定同一对象):
testSyncMethod:0
testSyncBlock:0
testSyncMethod:1
testSyncBlock:1
testSyncMethod:2
testSyncBlock:2
testSyncMethod:3
下面这个案例是上个案例的翻版(输出将是乱序的)
请大家体会:
package com.horizon.thread.classLock;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* synchronized (RunnableTest.class)
* 和 synchronized (this.getClass()) 是同等的
* @author wangxinchun
*
*/
public class SynchronizedStatic3 implements Runnable {
private static boolean flag = true;
private static synchronized void testSyncMethod() { // 注意static修改的同步方法,监视器=class
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testSyncMethod:" + i);
}
}
private void testNotSyncBlock() {
synchronized (this) { // 显示当前对象做为监视器
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testNotSyncBlock:" + i);
}
}
}
public void run() {
// flag是static的变量.所以,不同的线程会执行不同的方法,只有这样才能看到不同的锁定效果.(事实上此处是存在:race 条件)
if (flag) {
flag = false;
testSyncMethod();
} else {
flag = true;
testNotSyncBlock();
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(2);
SynchronizedStatic3 rt = new SynchronizedStatic3();
SynchronizedStatic3 rt1 = new SynchronizedStatic3();
exec.execute(rt);
exec.execute(rt1);
exec.shutdown();
}
}