一、先来看看作用域
这是一个线程类,run方法上面加上了synchronize关键字,目的是为了测试方法上面加锁作用的范围是这个实例还是整个类
public class SynchronizedThread implements Runnable{
private String name;
public SynchronizedThread(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public synchronized void run() {
System.out.println(name+" before");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+" after");
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
//开启10个线程让它跑,看看synchronized关键字放在方法上是对于对象有用还是对于类有用
for(int i =0;i<10;i++){
executorService.submit(new SynchronizedThread(i+""));
}
executorService.shutdown();
}
}
结果如下:
0 before
3 before
2 before
4 before
7 before
8 before
6 before
1 before
5 before
9 before
6 after
8 after
3 after
7 after
4 after
0 after
2 after
1 after
9 after
5 after
说明在一个实例调用run方法的同时,另一个实例也会调用run()方法
结论:synchronize关键字放在方法的前面,作用域是单个实例
下面来看synchronize(obj)的情况(同步代码块)
public class SynchronizedThread implements Runnable{
private String name;
public SynchronizedThread(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void run() {
synchronized (name) {
System.out.println("before");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("this is my name "+name);
}
}
}
测试类还是一样,
结果如下:
before
before
before
before
before
before
before
before
before
before
this is my name 3
this is my name 7
this is my name 2
this is my name 6
this is my name 0
this is my name 1
this is my name 4
this is my name 9
this is my name 5
this is my name 8
结论:synchronize(obj)是获得这个对象实例的锁,同一时间只能有一个方法块去操作这个实例,注意,我以上的测试全部都是排除作用域是类的情况,而并没有对实例的情况作为证明,想要证明的可以自己写测试方法证明,我这里仅仅排除了作用域为类而已
如果上面的synchronize(name)里面的name 改成this,那么作用域就是整个实例了
给静态方法加同步锁如下:
public class SynchronizedThread implements Runnable{
private String name;
public SynchronizedThread(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void run() {
test();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("after");
}
public synchronized static void test(){
System.out.println("this is a test!");
}
}
this is a test!
this is a test!
this is a test!
this is a test!
this is a test!
this is a test!
this is a test!
this is a test!
this is a test!
this is a test!
after
after
after
after
after
after
after
after
after
after
可以看出作用域是实例
下面是同步代码块锁住类:
public class SynchronizedThread implements Runnable{
private String name;
public SynchronizedThread(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void run() {
synchronized (SynchronizedThread.class) {
System.out.println("this is a test");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("after");
}
}
}
this is a test
after
this is a test
after
this is a test
after
this is a test
after
this is a test
after
this is a test
after
this is a test
after
this is a test
after
this is a test
after
this is a test
after
结论:采用synchronize(xxx.class)的方式,作用域是整个类