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被两个线程同一时候操作。这样就非常easy导致误操作。
怎样才干解决问题呢?用线程的同步技术。加上synchronizedkeyword
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)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实 ...
- Linux互斥和同步应用程序(一):posix线程和线程之间的相互排斥
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流.请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回 ...
- Android多线程研究(6)——多线程之间数据隔离
在上一篇<Android多线程研究(5)--线程之间共享数据>中对线程之间的数据共享进行了学习和研究,这一篇我们来看看怎样解决多个线程之间的数据隔离问题,什么是数据隔离呢?比方说我们如今开 ...
- java核心知识点学习----多线程并发之线程同步
1.什么是线程同步? 多线程编程是很有趣的事情,它很容易出现"错误情况",这种情况不是由编码造成的,它是由系统的线程调度造成的,当使用多个线程来访问同一个数据时,很容易出现&quo ...
- Linux多线程同步之相互排斥量和条件变量
1. 什么是相互排斥量 相互排斥量从本质上说是一把锁,在訪问共享资源前对相互排斥量进行加锁,在訪问完毕后释放相互排斥量上的锁. 对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会 ...
- 多线程状态与优先级、线程同步与Monitor类、死锁
一.线程状态 二.线程优先级 三.初步尝试多线程 class Program { static void Main(string[] args) { while (true) { MessagePri ...
- Linux同步与相互排斥应用(零):基础概念
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 当操作系统进入多道批处理系统时 ...
- UNIX网络编程卷1 server程序设计范式7 预先创建线程,以相互排斥锁上锁方式保护accept
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.预先创建一个线程池.并让每一个线程各自调用 accept 2.用相互排斥锁代替让每一个线 ...
随机推荐
- 【数据分析 R语言实战】学习笔记 第三章 数据预处理 (下)
3.3缺失值处理 R中缺失值以NA表示,判断数据是否存在缺失值的函数有两个,最基本的函数是is.na()它可以应用于向量.数据框等多种对象,返回逻辑值. > attach(data) The f ...
- spring-mvc hello world (1)
我学习一个程序,都是从DEMO开始的. 先不了解SPRING-MVC的原理,但一些小的概念还是需要了解的.由于之前有过SSH的工程经验,故基本的东东,不在叙述. 1.准备环境 JAR包:
- Linq详细介绍
声明----文档转载自:http://www.cnblogs.com/liulun/archive/2013/02/26/2909985.html 在说LINQ之前必须先说说几个重要的C#语言特性 一 ...
- excel vba 高级过滤
excel vba 高级过滤 Sub shaixuan() Dim database As Range '定义数据区域 Dim criteria_range As Range '定义条件区域 Dim ...
- Common.Logging.dll----------配置方式,可选引用,用于日志输出
1.简介common logging是一个通用日志接口,log4net是一个具体实现. common logging可以把输出连接到其他非log类上, 如EntLib的日志.NLog等 2.使用接下来 ...
- 「二叉搜索树 / set / 朝鲜树 / 替罪羊树」快速排序
要求 给定n个数,对这n个数进行排序 这题当然可以直接调用sort #include<cstdio> #include<vector> #define ll long long ...
- Flask框架 之模版
一.过滤器 safe:禁用转义: <p>{{ '<em>hello</em>' | safe }}</p> capitalize:把变量值的首字母转成大 ...
- caffe blob理解
blob数据结构是caffe中基本的数据存储单元,它主要存储的数据是网络中的中间数据变量,比如各层的输入和输出:代价函数关于网络各层参数的梯度. blob中除了存储数据外,还有一些标记数据的参数,以下 ...
- numpy add
在numpy中,'+' 和add 是一样的 np.add(x1, x2) x1+x2 有种特殊情况需要注意,x1和x2的shape不一样的加法: 两个shape不一样的array相加后会变成一个com ...
- Android中notifyDataSetInvalidated()和notifyDataSetChanged()有什么区别
看下源码中对于这两个方法 public void notifyDataSetChanged () 该方法内部实现了在每个观察者上面调用onChanged事件.每当发现数据集有改变的情况,或者读取 ...