首页 > 代码库 > Android多线程研究(3)——线程同步和相互排斥及死锁

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)——线程同步和相互排斥及死锁