zoukankan      html  css  js  c++  java
  • 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——继续深造——从安装Android Studio 2.0开始(详)
    PHP——安装wampserver丢失MSVCR110.dll
    Marza Gift for GDC 2016
    Retrieve OpenGL Context from Qt 5.5 on OSX
    Space Time Varying Color Palette
    Screen Space Depth Varying Glow based on Heat Diffusion
    Visualization of Detail Point Set by Local Algebraic Sphere Fitting
    Glass Dragon
    Jump Flood Algorithms for Centroidal Voronoi Tessellation
    京都之行
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468941.html
Copyright © 2011-2022 走看看