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()方法发起一次异步的线程执行很简单 但是该方法最大的问题是 ...
随机推荐
- 热点共享SS网络
# 测试系统: Ubuntu 16.04 LTS-lxde-ARM # ***-libev 安装脚本源于 秋水逸冰: https://teddysun.com/358.html # ss-tproxy ...
- vmware-虚拟机播放器的下载、安装
如果是在window下安装的话: 1.下载vmware: 到官网下载免费个人版本 https://my.vmware.com/cn/web/vmware/free#desktop_end_user_c ...
- Day2平衡树笔记
线段树不支持的操作:删除,插入 常见的平衡树 treap 慢||好写 sbt(大小平衡的树) 非常快 比较好写 ||功能不全 rbt 红黑树 特别快 || 非常难写 以上操作支持插入删除O(Nlo ...
- 在Fedora 14 alpha 下测试Kvm情况(视频)
今天刚忙完,便抽空做了fc14下的虚拟机的测试,总体感觉在2.6.35的kernel下启动和配置虚拟机的速度比原来要快乐许多,下面就带着各位体验一下吧.(硬件测试环境:IBM R52,2g内存,物理机 ...
- BZOJ2157: 旅游(LCT)
Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间 ...
- Eclipse导入Maven项目出现错误:Unsupported IClasspathEntry kind=4
使用Eclipse导入Maven项目失败,提示: An internal error occurred during: "Importing Maven projects". Un ...
- drawable-实现图片旋转
今天因为需要,所以要让一个图片随着某种需要进行旋转.但是,又不能一张张的做动态图片.所以就在网上找了这么个方法.但是,这个方法有个问题,就是虽然能实现图片的旋转.但是,图片旋转以后会进行缩放.具体原因 ...
- golang sort
package main import ( "fmt" "strings" "sort" ) type Animals []string f ...
- 00099_commons-IO
1.导入classpath (1)加入classpath的第三方jar包内的class文件才能在项目中使用: (2)创建lib文件夹: (3)将commons-io.jar拷贝到lib文件夹: (4) ...
- SSH进阶(2)——用Struts拦截器实现登陆限制
拦截器从字面意思来看就是限制.限制用户訪问某些网页.在Action提出请求之前用拦截器来做权限设置,让符合的用户跳入对应的界面中.近期做的一个商城项目中就用到了自己定义的拦截器,实现了一个简单的ses ...