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();
    }
}
时间: 2024-08-18 12:02:40

Android多线程研究(3)——线程同步和相互排斥及死锁的相关文章

线程同步与相互排斥:相互排斥锁

为什么须要相互排斥锁? 在多任务操作系统中,同一时候执行的多个任务可能都须要使用同一种资源.这个过程有点类似于,公司部门里.我在使用着打印机打印东西的同一时候(还没有打印完).别人刚好也在此刻使用打印机打印东西,假设不做不论什么处理的话,打印出来的东西肯定是错乱的. 以下我们用程序模拟一下这个过程.线程一须要打印" hello ",线程二须要打印" world ",不加不论什么处理的话.打印出来的内容会错乱: [cpp] view plaincopy #includ

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,

Android多线程研究(9)——线程锁Lock

在前面我们在解决线程同步问题的时候使用了synchronized关键字,今天我们来看看Java 5.0以后提供的线程锁Lock. Lock接口的实现类提供了比使用synchronized关键字更加灵活和广泛的锁定对象操作,而且是以面向对象的方式进行对象加锁. @Override public void run() { while(true){ Lock lock = new ReentrantLock(); try { lock.lock(); Thread.sleep(new Random()

Android多线程研究(5)——线程之间共享数据

一.如果是每个线程都执行相同的代码,则可以使用同一个Runnable来实现共享 public class MultiThreadShareData { public static void main(String[] args) { new Thread(new ShareData()).start(); new Thread(new ShareData()).start(); } static class ShareData implements Runnable{ private int j

Android多线程研究(1)——线程基础及源代码剖析

从今天起我们来看一下Android中的多线程的知识,Android入门easy,可是要完毕一个完好的产品却不easy,让我们从线程開始一步步深入Android内部. 一.线程基础回想 package com.maso.test; public class TraditionalThread { public static void main(String[] args) { /* * 线程的第一种创建方式 */ Thread thread1 = new Thread(){ @Override p

Android多线程研究(1)——线程基础及源码剖析

从今天起我们来看一下Android中的多线程的知识,Android入门容易,但是要完成一个完善的产品却不容易,让我们从线程开始一步步深入Android内部. 一.线程基础回顾 package com.maso.test; public class TraditionalThread { public static void main(String[] args) { /* * 线程的第一种创建方式 */ Thread thread1 = new Thread(){ @Override publi

Android多线程研究(7)——Java5中的线程并发库

从这一篇开始我们将看看Java 5之后给我们添加的新的对线程操作的API,首先看看api文档: java.util.concurrent包含许多线程安全.测试良好.高性能的并发构建块,我们先看看atomic包下的AtomicInteger. import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { private static AtomicInteger data = new Atomic

.NET面试题解析(07)-多线程编程与线程同步

系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等,本文只是从常见面试题的角度(也是开发过程中常用)去深入浅出线程相关的知识.如果想要系统的学习多线程,没有捷径的,也不要偷懒,还是去看专业书籍的比较好. 常见面试题目: 1. 描述线程与进程的区别? 2. 为什么GUI不支持跨线程访问控件?一般如何解决这个问题? 3. 简述后台线程和前台线程的区别? 4. 说说常

Android多线程研究(4)——从一道面试题说起

有一道这种面试题:开启一个子线程和主线程同一时候运行,子线程输出10次后接着主线程输出100次,如此重复50次.先看以下代码: package com.maso.test; /** * * @author Administrator * 两个线程,当中是一个主线程,第一个线程先运行输出10次,主线程接着运行输出100次,如此重复50次 */ public class ThreadTest3 implements Runnable{ private static Test test; @Overr