• 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(); } }






  • 相关阅读:
    验证整数或小数
    数据库的连接查询比较
    批处理按钮
    事务 SQL
    关于GridView模板的一些总结
    C#数据结构之线性表
    C#面向对象基础
    C#集合类:动态数组、队列、栈、哈希表、字典
    如何更改master中WebParts中自定义控件的值。
    如何取得web.config中connectings中的值
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7147512.html
Copyright © 2020-2023  润新知