Android多线程研究(3)——线程同步和互斥及死锁
为什么会有线程同步的概念呢?为什么要同步?什么是线程同步?先看一段代码:
package com.maso.test;
public class ThreadTest2 implements Runnable{
private TestObj testObj = new TestObj();
public static void main(String[] args) {
ThreadTest2 tt = new ThreadTest2();
Thread t1 = new Thread(tt, "thread_1");
Thread t2 = new Thread(tt, "thread_2");
t1.start();
t2.start();
}
@Override
public void run() {
for(int j = 0; j < 10; j++){
int i = fix(1);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : i = " + i);
}
}
public int fix(int y){
return testObj.fix(y);
}
public class TestObj{
int x = 10;
public int fix(int y){
return x = x - y;
}
}
}
输出结果后,就会发现变量x被两个线程同时操作,这样就很容易导致误操作。如何才能解决这个问题呢?用线程的同步技术,加上synchronized关键字
public synchronized int fix(int y){
return testObj.fix(y);
}
加上同步后,就可以看到有序的从9输出到-10.
如果加到TestObj类的fix方法上能不能实现同步呢?
public class TestObj{
int x = 10;
public synchronized int fix(int y){
return x = x - y;
}
}
如果将synchronized加到方法上则等价于
synchronized(this){
}
可以判断出两个线程使用的TestObj类的同一个实例testOjb,所以后实现同步,但是输出的结果却不是理想的结果。这是因为当A线程执行完x = x - y后还没有输出则B线程已经进入开始执行x = x - y.
所以像下面这样输出就不会有什么问题了:
public class TestObj{
public TestObj(){
System.out.println("调用了构造函数");
}
int x = 10;
public synchronized int fix(int y){
x = x - y;
System.out.println(Thread.currentThread().getName() + " : x = " + x);
return x;
}
}
如果将外部的fix方法修改如下:
public int fix(int y){
ax++ ;
if(ax%2 == 0){
return testObj.fix(y, testObj.str1);
}else{
return testObj.fix(y, testObj.str2);
}
}
public class TestObj{
String str1 = "a1";
String str2 = "a2";
public TestObj(){
System.out.println("调用了构造函数");
}
int x = 10;
public int fix(int y, String str){
synchronized (str) {
x = x - y;
System.out.println(Thread.currentThread().getName() + " : x = " + x);
}
return x;
}
}
此时synchronized中的str对象不是同一个对象,所以两个线程所持有的对象锁不是同一个,这样就不能实现同步。要实现线程之间的互斥就要使用同一个对象锁。
什么是死锁呢?举个例子就是比如你和同学租了个两室的房子,你拿着你房子的钥匙,你同学拿着他房子的钥匙,现在你在房子等你同学将他的钥匙给你然后你进他房子,你同学在他的房子等你将钥匙给他然后他进你的房子,这样就死锁了。
package com.maso.test;
public class ThreadDieSock implements Runnable {
private int flag = 1;
private Object obj1 = new Object(), obj2 = new Object();
public void run() {
System.out.println("flag=" + flag);
if (flag == 1) {
synchronized (obj1) {
System.out.println("我已经锁定obj1,休息0.5秒后锁定obj2去!");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2) {
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (obj2) {
System.out.println("我已经锁定obj2,休息0.5秒后锁定obj1去!");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1) {
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
ThreadDieSock run01 = new ThreadDieSock();
ThreadDieSock run02 = new ThreadDieSock();
run01.flag = 1;
run02.flag = 0;
Thread thread01 = new Thread(run01);
Thread thread02 = new Thread(run02);
System.out.println("线程开始喽!");
thread01.start();
thread02.start();
}
}
Android多线程研究(3)——线程同步和互斥及死锁的更多相关文章
- .NET面试题解析(07)-多线程编程与线程同步
系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等, ...
- .NET面试题解析(07)-多线程编程与线程同步 (转)
http://www.cnblogs.com/anding/p/5301754.html 系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实 ...
- Android多线程研究(6)——多线程之间数据隔离
在上一篇<Android多线程研究(5)--线程之间共享数据>中对线程之间的数据共享进行了学习和研究,这一篇我们来看看怎样解决多个线程之间的数据隔离问题,什么是数据隔离呢?比方说我们如今开 ...
- 线程同步 - POSIX互斥锁
线程同步 - POSIX互斥锁 概括 本文讲解POSIX中互斥量的基本用法,从而能达到简单的线程同步.互斥量是一种特殊的变量,它有两种状态:锁定以及解锁.如果互斥量是锁定的,就有一个特定的线程持有或者 ...
- java核心知识点学习----多线程并发之线程同步
1.什么是线程同步? 多线程编程是很有趣的事情,它很容易出现"错误情况",这种情况不是由编码造成的,它是由系统的线程调度造成的,当使用多个线程来访问同一个数据时,很容易出现&quo ...
- Android多线程研究(3)——线程同步和相互排斥及死锁
为什么会有线程同步的概念呢?为什么要同步?什么是线程同步?先看一段代码: package com.maso.test; public class ThreadTest2 implements Runn ...
- Android多线程研究(9)——线程锁Lock
在前面我们在解决线程同步问题的时候使用了synchronized关键字,今天我们来看看Java 5.0以后提供的线程锁Lock. Lock接口的实现类提供了比使用synchronized关键字更加灵活 ...
- linux线程同步(1)-互斥量
一.概述 互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...
- 细说C#多线程那些事 - 线程同步和多线程优先级
上个文章分享了一些多线程的一些基础的知识,今天我们继续学习. 一.Task类 上次我们说了线程池,线程池的QueueUserWorkItem()方法发起一次异步的线程执行很简单 但是该方法最大的问题是 ...
随机推荐
- Filebeat-1.3.1安装和设置(图文详解)(多节点的ELK集群安装在一个节点就好)(以Console Output为例)
前期博客 Filebeat的下载(图文讲解) 前提 Elasticsearch-2.4.3的下载(图文详解) Elasticsearch-2.4.3的单节点安装(多种方式图文详解) Elasticse ...
- Ubuntu系统简介
1.ubuntu 远程连接 需要开启ssh 服务 sudo apt-get install openssh-server service ssh start|stop|restart 2.查看Linu ...
- C语言的多行宏定义
一.多行宏定义的使用 最近在跟STM32L011K4T6低功耗的源代码,发现使用了多行的宏定义来封装函数,记得之前把\给删除掉,编译程序就一直报错. \是续行操作符,也就是宏定义一行写不完,需要多行写 ...
- Boost解析xml——xml写入
<?xml version="1.0" encoding="utf-8"?> <Config> <Item name=" ...
- eclipse git冲突解决
1.工程->Team->同步: 2.从远程pull至本地,就会出现如下内容: 3.使用Merge Tool,执行第二项 4.再手动修改 4.修改后的文件需要添加到Git index中去: ...
- session应用二
从session中获取mapper对象,利用mapper对象进行增删改查 Date now = new Date(); SqlSession session = this.yangchebaoDbMa ...
- cocos2d-x嵌入移动MM短代支付IAP2.4的SDK,点击支付崩溃的解决的方法
凡是用IAP2.4,调用purchase.order 游戏崩溃.logcat报错是: 06-16 18:43:42.944: E/AndroidRuntime(8526): FATAL EXCEPTI ...
- 学习笔记:Vue——动态组件&异步组件
动态组件 01.在动态组件上使用keep-alive,保持组件的状态,以避免反复重渲染导致的性能问题. <!-- 失活的组件将会被缓存!--> <keep-alive> < ...
- (JavaScript基础向)sort()方法里的排序函数的理解
比较常见的解释可以看这里:js的sort()方法,这篇博客写得挺好的,一般的应用的理解已经足够了. 但是如果要活用sort()方法里面的参数——也就是排序函数的话,可能就比较难理解了. 然后我就总结出 ...
- Spring MVC基础了解
参考网址:https://www.yiibai.com/spring_mvc/springmvc_overview.html Spring框架相关 Spring Security 一个灵活强大的身份验 ...