java多线程-synchronized
一、线程安全问题
多线程操作各自线程创建的资源的时候,不存在线程安全问题。但多线程操作同一个资源的时候就会出现线程安全问题。下例为两个线程操作同一个name资源时发生的问题。
class TestSyn {
public static void main(String[] args) throws Exception {
Resource resource = new Resource();
new Thread() {
@Override
public void run() {
while (true) {
r.sayb();
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
r.sayq();
}
}
}.start();
}
}
class Resource {
private String name;
public void sayb() {
name = "bbb";
System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb
}
public void sayq() {
name = "qqqqqq";
System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb
}
}
/**
*
Thread-1qqqqqq
Thread-1qqqqqq
Thread-0qqqqqq //其中一段错误信息,Thread-0线程也打印了qqqqqq
Thread-0bbb
Thread-0bbb
*/
问题出现过程:
Thread-0获取执行权执行name="bbb"。
Thread-1获得执行权执行name="qqqqqq"。
Thread-0重新获得执行权执行打印指令,这时Thread-0就打印出了qqqqqq。
二、synchronized代码块
如果name赋值,打印name是一个原子操作就可以避免线程安全问题。
java中synchronized可以标记一段代码,达到原子操作的效果。
- 当一个线程执行标记有synchronized代码时将获得该对象的锁,然后开始执行synchronized标记的代码。
- 每一个对象只有一个锁,因此其他线程无法获得该对象锁。
- 其他线程如果这时候也执行到了标记有synchronized的代码将阻塞,直到获得对象锁的线程执行完synchronized标记的代码。
- 然后持有锁的线程释放锁。
- 其他线程开始争夺锁,回到第1步。
synchronized标记代码有两种方式:
//synchronized代码块
class Resource {
private String name; public void sayb() {
synchronized (this){
name = "bbb";
System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb
}
//...其他代码
} public void sayq() {
synchronized (this){
name = "qqqqqq";
System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb
}
//...其他代码
}
}
//synchronized方法
class Resource {
private String name; public synchronized void sayb() {
name = "bbb";
System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb
//...其他代码
} public synchronized void sayq() {
name = "qqqqqq";
System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb
//...其他代码
}
}
上例中两个线程执行的是同一个对象的方法,因此他们抢夺同一个锁,一个线程执行的时候,另一个线程阻塞。
两种方法有些不同点:
- synchronized方法标记在非static方法上,线程获得的锁为this,例子中为resource对象。若标记在static方法上则线程获得的锁为Resource.class对象。
- synchronized标记在代码块上,可以由用户自己指定,而且代码块的范围也可以自己指定。因此synchronized代码块比synchronized方法更加灵活。
注意:
- 使用synchronized会降低性能,使用时尽量缩小synchronized标记的范围。
- synchronized不会死锁,异常抛出时虚拟机会释放锁。
三、monitor与锁的重入
class Test {
public static void main(String[] args) {
syn();
}
private static synchronized void syn(){
synchronized (Test.class){
synchronized (Test.class){
synchronized (Test.class){
System.out.println(1);
}
}
}
}
}
- 虚拟机为每个对象分配了一个monitor。
- 前面说到当一个线程进入synchronized代码块,就获得了对象锁,实际上是monitor的计数器++。
- monitor的计数器>0时,线程获得锁,因此上面的代码monitor的计数器每次进入一个synchronized代码块monitor的计数器++,结束一个代码块monitor的计数器--。
- monitor的计数器=0时,线程才会释放锁。
这就是锁的重入。
java多线程-synchronized的更多相关文章
- Java 多线程 —— synchronized关键字
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- Java多线程synchronized同步
非线程安全问题 “非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程问题”.也即是说,方法中的变量永远是线程安全的. 如果多个线程共同访问1个对象中的实例变量,则可能线程 ...
- JAVA多线程synchronized详解
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 当两个并发线程访问同一个对象object中的这个synchronized(this)同 ...
- java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized ...
- java 多线程 synchronized与lock的通信机制等问题,结合相应实例说明
1. 利用多线程实现如下需求: 写两个线程,一个线程打印1~52,另一个线程打印A~Z,打印顺序是12A34B...5152Z: 2. 使用synchronized 实现 public class T ...
- Java多线程-synchronized关键字
进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程 Ja ...
- Java多线程synchronized关键字
synchronized关键字代表着同步的意思,在Java中被synchronized修饰的有三种情况 1.同步代码块 //锁为objsynchronized(obj){ while(true){ i ...
- Java 多线程 - Synchronized关键字
目录 1-Synchronized 关键字概述 2- Synchronized关键字作用域 3- Synchronized 原理(反编译指令解释) 正文 1-Synchronized 关键字概述 由于 ...
- java多线程:synchronized和lock比较浅析
转载:http://www.toutiao.com/a6392135944652587266/?tt_from=weixin&utm_campaign=client_share&app ...
随机推荐
- Linux下面rpm命令和mount命令详解
在Linux下面我们经常会安装一些软件包,还有挂载命令.接下来,我们通过一些实例来演示这些命令的使用.. 第一步:我们先在linux下面挂载光盘,先进入到根目录,然后切换到根下面的/mnt目录,因为/ ...
- 设计模式06: Adapter 适配器模式(结构型模式)
Adapter 适配器模式(结构型模式) 适配(转换)的概念无处不在:电源转接头.电源适配器.水管转接头... 动机(Motivation)在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ...
- [database] postgresql 外网访问
配置 环境 ubuntu 14.04 LTS 版本 postgresql version 9.3 修改监听地址 编辑 /etc/postgresql/9.3/main/postgresql.conf ...
- [other] 代码量代码复杂度统计-lizard
[other] 代码量代码复杂度统计-lizard lizard的可以用来统计下面的一些数据 不包含代码注释的代码行数 CCN 代码的复杂度,也就是分支复杂度 token的个数(关键字,标示符,常量, ...
- Xcode打包提交至itunes connect后,提交审核成功,随后出现二进制文件无效
1.问题描述 Xcode打包提交至itunes connect后,提交审核成功,应用处于待审核状态,过了大概半个小时状态更改为二进制文件无效 2.原因分析 2.1 登陆在苹果中预留的邮箱 ---- 邮 ...
- ORB SLAM2 学习笔记
cd ~/Documents/demos/ORB_SLAM2 ./Examples/RGB-D/rgbd_tum Vocabulary/ORBvoc.txt Examples/RGB-D/TUM1.y ...
- Charles设置可抓https的包
一.help 二.proxy
- 【转】C#使用Oracle.ManagedDataAccess.dll
源地址:https://www.cnblogs.com/goldenbridge/p/7812081.html
- Pycharm使用的一些问题!!!
1.pycharm如何更改主题.如何更改字体的大小? 2.pycharm如何import第三方库? 1.更改主题和字体大小 主题变暗,字体变大! 2.如何导入第三方库?
- Python基本数据类型集合、格式化、函数
一.变量总结 1.1 变量定义 记录某种状态或者数值,并用某个名称代表这个数值或状态. 1.2 变量在内存中的表现形式 Python 中一切皆为对象,数字是对象,列表是对象,函数也是对象,任何东西都是 ...