对synchronized(this)的一些理解
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
举例说明:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
- package ths;
- public class Thread1 implements Runnable {
- public void run() {
- synchronized (this) {
- for (int i = 0; i < 5; i++) {
- System.out.println(Thread.currentThread().getName()
- + " synchronized loop " + i);
- }
- }
- }
- 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();
- }
- }
package ths;
public class Thread1 implements Runnable {
public void run() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()
+ " synchronized loop " + i);
}
}
}
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
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
- package ths;
- public class Thread2 {
- public void m4t1() {
- synchronized (this) {
- int i = 5;
- while (i-- > 0) {
- System.out
- .println(Thread.currentThread().getName() + " : " + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
- }
- public void m4t2() {
- int i = 5;
- while (i-- > 0) {
- System.out.println(Thread.currentThread().getName() + " : " + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
- public static void main(String[] args) {
- final Thread2 myt2 = new Thread2();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- myt2.m4t1();
- }
- }, "t1");
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- myt2.m4t2();
- }
- }, "t2");
- t1.start();
- t2.start();
- }
- }
package ths;
public class Thread2 {
public void m4t1() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out
.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread(new Runnable() {
public void run() {
myt2.m4t1();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
myt2.m4t2();
}
}, "t2");
t1.start();
t2.start();
}
}
结果:
t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
//修改Thread2.m4t2()方法:
- public void m4t2() {
- synchronized (this) {
- int i = 5;
- while (i-- > 0) {
- System.out
- .println(Thread.currentThread().getName() + " : " + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
- }
public void m4t2() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out
.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
//修改Thread2.m4t2()方法如下:
- public synchronized void m4t2() {
- int i = 5;
- while (i-- > 0) {
- System.out.println(Thread.currentThread().getName() + " : " + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
public synchronized void m4t2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
五、以上规则对其它对象锁同样适用:
- package ths;
- public class Thread3 {
- class Inner {
- private void m4t1() {
- int i = 5;
- while (i-- > 0) {
- System.out.println(Thread.currentThread().getName()
- + " : Inner.m4t1()=" + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
- private void m4t2() {
- int i = 5;
- while (i-- > 0) {
- System.out.println(Thread.currentThread().getName()
- + " : Inner.m4t2()=" + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
- }
- private void m4t1(Inner inner) {
- synchronized (inner) { // 使用对象锁
- inner.m4t1();
- }
- }
- private void m4t2(Inner inner) {
- inner.m4t2();
- }
- public static void main(String[] args) {
- final Thread3 myt3 = new Thread3();
- final Inner inner = myt3.new Inner();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- myt3.m4t1(inner);
- }
- }, "t1");
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- myt3.m4t2(inner);
- }
- }, "t2");
- t1.start();
- t2.start();
- }
- }
package ths;
public class Thread3 {
class Inner {
private void m4t1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName()
+ " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName()
+ " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized (inner) { // 使用对象锁
inner.m4t1();
}
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread(new Runnable() {
public void run() {
myt3.m4t1(inner);
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
public void run() {
myt3.m4t2(inner);
}
}, "t2");
t1.start();
t2.start();
}
}
结果:
尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
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
现在在Inner.m4t2()前面加上synchronized:
- private synchronized void m4t2() {
- int i = 5;
- while (i-- > 0) {
- System.out.println(Thread.currentThread().getName()
- + " : Inner.m4t2()=" + i);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ie) {
- }
- }
- }
private synchronized void m4t2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName()
+ " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
结果:
尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方
对synchronized(this)的一些理解的更多相关文章
- volatile和synchronized与lock的理解
volatile 特征: a:可见性:一个线程修改了某个共享变量的值,其他线程能够立马得知这个修改. b:禁止特定的处理器重排序. volatile的内存语义: 1.当写一个volatile变量的时候 ...
- java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ...
- 深入理解java中的synchronized关键字
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...
- 计算机程序的思维逻辑 (66) - 理解synchronized
上节我们提到了多线程共享内存的两个问题,一个是竞态条件,另一个是内存可见性,我们提到,解决这两个问题的一个方案是使用synchronized关键字,本节就来讨论这个关键字. 用法 synchroniz ...
- 深入理解Java并发之synchronized实现原理
深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...
- Java编程的逻辑 (66) - 理解synchronized
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- 深入理解并发编程之----synchronized实现原理
版权声明:本文为博主原创文章,请尊重原创,未经博主允许禁止转载,保留追究权 https://blog.csdn.net/javazejian/article/details/72828483 [版权申 ...
- synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解
本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...
- 【Java并发编程实战】-----synchronized
在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者.写相同的数据,访问相同的文件等等.对于这种情况如果我们不加以控制,是非常容易导致错误的.在java中,为了解决这个问题,引入临界区概念. ...
随机推荐
- P4578 [FJOI2018]所罗门王的宝藏
传送门 考虑一个位置答案传递性,如果某个位置的红宝石转动确定了,那么会引起连锁反应: 如图,绿色的转动确定了,那么那两个蓝色的转动也确定了 自己手玩一下,发现如果有解那么随便找一个开始然后一路玩下去最 ...
- vue 中引用 百度地图
1.在 http://lbsyun.baidu.com/ 申请 秘钥 2.在index.html文件中引入 <script src="http://api.map.baidu.com/ ...
- Android so 库按需打包
Fresco 大部分的代码是由Java写的,但是里面也有很多C++的代码.C++代码必须根据Android 设备的CPU类型(通常称为”ABIs”)进行编译.目前Fresco支持五种 ABI: arm ...
- string查找字符(串)
在C语言中 strchr 和 strstr函数都被包含在<string.h>头文件中,也就是要调用它们时要在程序前面包含<string.h>头文件,也就是写这个语句:#incl ...
- maven 引入本地 jar
$ 参考1 : https://www.cnblogs.com/lixuwu/p/5855031.html ! 注: 参考1中的第二种方法,作者并未实际尝试,我尝试了,虽然在eclipse 中编译不报 ...
- ansible 实战项目之文件操作(二)
一,前言 如果没有安装好的话看我以前的贴子哦!! 上次安装已经确定通了,所以下面步骤应该是完全ok的 特点: (1).轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可: (2 ...
- Servlet3.0的文件上传功能
在Servlet3.0之前,文件上传需要借助于第三方插件,在Servlet3.0之后,Servlet本身开始支持文件上传功能. 获取上传的文件可以通过HTTPServletRequest的getPar ...
- 关于微信小程序的动态跳转
最近在研究微信小程序.在做一个简单的购物小程序时,遇到一个问题:如何通过扫码实现动态的跳转页面功能, 通过研究终于找到了解决方法: 首先当然要实现扫码解析功能js的代码: click: functio ...
- MySQL 查询多张表中相同字段的最大值
MySql : 有N张表,N未知,每张表都有一个字段(id),每张表的字段结构不完全一样,如何查询所有表里面所有id的最大值?如下图所示: 对上面三张表进行操作的话,结果应该为:9 SQL语句: se ...
- 微信token验证源码分享(c#版)
在开发时遇到一个问题: 上线后提交申请微信提示"您的服务器没有正确响应token验证...",我查看日志发现根本就没有接收到来自微信的参数. 后来我又记录了微信请求方式和请求的字符 ...