Android 同步锁死锁,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();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值