java之Synchronized(锁住对象和锁住代码)
1、问题
Synchronized我们一般都知道是锁,但是我们怎么区分是锁对象还是锁代码呢?
2、测试Demo
-
package leetcode.chenyu.test;
-
-
public class Synchronized {
-
-
class Test {
-
public synchronized void testFirst() {
-
print("testFirst");
-
}
-
-
public void testSecond() {
-
synchronized(this) {
-
print("testSecond");
-
}
-
}
-
-
public void testThird() {
-
synchronized(Test.class) {
-
print("testThird");
-
}
-
}
-
-
public void print(String method) {
-
System.out.println(method + "start");
-
try {
-
Thread.sleep(100);
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
System.out.println(method + "end");
-
}
-
}
-
-
-
class TestThread extends Thread {
-
-
public int mType = 0;
-
public Test mTest = null;
-
-
public TestThread(int type, Test test) {
-
this.mType = type;
-
this.mTest = test;
-
}
-
-
public void run() {
-
if (mTest == null) {
-
if (mType == 1) {
-
Test test = new Test();
-
test.testFirst();
-
}
-
else if (mType == 2) {
-
Test test = new Test();
-
test.testSecond();
-
}
-
else if (mType == 3) {
-
Test test = new Test();
-
test.testThird();
-
}
-
} else {
-
if (mType == 1) {
-
mTest.testFirst();
-
}
-
else if (mType == 2) {
-
mTest.testSecond();
-
}
-
else if (mType == 3) {
-
mTest.testThird();
-
}
-
}
-
}
-
}
-
-
-
public static void main(String[] args) {
-
Synchronized syn = new Synchronized();
-
Test test = syn.new Test();
-
for (int i = 0; i < 5; ++i) {
-
syn.new TestThread(1, null).start();
-
}
-
}
-
}
-
3、运行结果和分析
1)、按照上面的运行结果
-
testFirststart
-
testFirststart
-
testFirststart
-
testFirststart
-
testFirststart
-
testFirstend
-
testFirstend
-
testFirstend
-
testFirstend
-
testFirstend
2)、把for循环里面的代码换如下
syn.new TestThread(2, null).start();
运行结果如下
-
testSecondstart
-
testSecondstart
-
testSecondstart
-
testSecondstart
-
testSecondstart
-
testSecondend
-
testSecondend
-
testSecondend
-
testSecondend
-
testSecondend
对于上面1)、2)、两种情况,synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段,锁的是对象,也就是锁的本身this, 由于每个线程都新构建了一个新的对象,所以加了synchronized没有锁住。
3)、把for循环里面的代码换如下
syn.new TestThread(1, test).start();
syn.new TestThread(2, test).start();
运行结果都一样如下
-
testSecondstart
-
testSecondend
-
testSecondstart
-
testSecondend
-
testSecondstart
-
testSecondend
-
testSecondstart
-
testSecondend
-
testSecondstart
-
testSecondend
这里由于我们几个现场都共用一个对象,所以对象固定了,所以就锁住了,其它线程在没有释放锁的时候,进不来。
4)、把for循环里面的代码换如下
syn.new TestThread(3, null).start();
syn.new TestThread(3, test).start();
结果都如下
-
testThirdstart
-
testThirdend
-
testThirdstart
-
testThirdend
-
testThirdstart
-
testThirdend
-
testThirdstart
-
testThirdend
-
testThirdstart
-
testThirdend
synchronized(Test.class)实现了全局锁的效果,不管对象是不是一样的,都是同样的效果,就锁住代码了
我么一般用这个比较多。
4、总结
1、synchronized加在非静态方法前和synchronized(this)都是锁住了这个类的对象,如果多线程访问,对象不同,就锁不住,对象固定是一个,就可锁住。
2、synchronized(类名.class)和加在静态方法前,是锁住了代码块,不管多线程访问的时候对象是不是同一个,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步,缩小锁的粒度。
4、总结
文章来源: chenyu.blog.csdn.net,作者:chen.yu,版权归原作者所有,如需转载,请联系作者。
原文链接:chenyu.blog.csdn.net/article/details/80646679
- 点赞
- 收藏
- 关注作者
评论(0)