• synchronized关键字


    介绍synchronized关键字之前有必要阐述一下线程安全的概念。“非线程安全”会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”,也就是取到的数据其实是被更改过的,如果是方法内部的私有变量不存在“非线程安全”的问题;而“线程安全”就是获得的实例变量的值是经过同步处理的,不会出现脏读的现象。synchronized就是保证同步的。

    package chapter2.synch.method;
    
    public class MyObject {
    	
    	synchronized public void methodA() {
    		try {
    			System.out.println("begin methodA threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
    			Thread.sleep(5000);
    			System.out.println("end methodA threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	synchronized public void methodB() {
    		try {
    			System.out.println("begin methodB threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
    			Thread.sleep(2000);
    			System.out.println("end methodB threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public void methodC() {
    		try {
    			System.out.println("begin methodC threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
    			Thread.sleep(2000);
    			System.out.println("end methodC threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public void methodD() {
    		try {
    			synchronized (this) {
    				System.out.println("begin methodD threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
    				Thread.sleep(2000);
    				System.out.println("end methodD threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public void methodE() {
    		try {
    			Object object = new Object();
    			synchronized (object) {
    				System.out.println("begin methodE threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
    				Thread.sleep(2000);
    				System.out.println("end methodE threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public void methodF(Object object) {
    		try {
    			synchronized (object) {
    				System.out.println("begin methodF threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
    				Thread.sleep(2000);
    				System.out.println("end methodF threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    
    package chapter2.synch.method;
    
    public class ThreadA extends Thread{
    	
    	private MyObject myObject;
    
    	public MyObject getMyObject() {
    		return myObject;
    	}
    
    	public void setMyObject(MyObject myObject) {
    		this.myObject = myObject;
    	}
    	
    	@Override
    	public void run() {
    		super.run();
    		myObject.methodA();
    	}
    
    }
    
    
    package chapter2.synch.method;
    
    public class ThreadB extends Thread{
    	
    	private MyObject myObject;
    
    	public MyObject getMyObject() {
    		return myObject;
    	}
    
    	public void setMyObject(MyObject myObject) {
    		this.myObject = myObject;
    	}
    	
    	@Override
    	public void run() {
    		super.run();
    		myObject.methodB();
    	}
    
    }
    
    package chapter2.synch.method;
    
    public class Run {
    
    	public static void main(String[] args) {
    		MyObject myObject = new MyObject();
    		ThreadA threadA = new ThreadA();
    		threadA.setMyObject(myObject);
    		threadA.setName("A");
    		
    		ThreadB threadB = new ThreadB();
    		threadB.setMyObject(myObject);
    		threadB.setName("B");
    		
    		threadA.start();
    		threadB.start();
    		
    	}
    }
    

     运行结果:(同步执行)

    begin methodA threadName=A--beginTime:1560936665128
    end methodA threadName=A--endTime:1560936670128
    begin methodB threadName=B--beginTime:1560936670128
    end methodB threadName=B--endTime:1560936672128

    如果ThreadB 修改成myObject.methodC();

    运行结果:(异步执行)

    begin methodC threadName=B--beginTime:1560936788821
    begin methodA threadName=A--beginTime:1560936788821
    end methodC threadName=B--endTime:1560936790821
    end methodA threadName=A--endTime:1560936793821

    如果ThreadB 修改成myObject.methodD();

    运行结果:(同步执行)

    begin methodD threadName=B--beginTime:1560936856169
    end methodD threadName=B--endTime:1560936858169
    begin methodA threadName=A--beginTime:1560936858169
    end methodA threadName=A--endTime:1560936863169

    如果ThreadB 修改成myObject.methodE();

    运行结果:(异步执行)

    begin methodE threadName=B--beginTime:1560936949062
    begin methodA threadName=A--beginTime:1560936949062
    end methodE threadName=B--endTime:1560936951062
    end methodA threadName=A--endTime:1560936954062

    代码做如下修改:

    package chapter2.synch.method;
    
    public class ThreadA extends Thread{
        
        private MyObject myObject;
        
        private Object object;
    
        public Object getObject() {
            return object;
        }
    
        public void setObject(Object object) {
            this.object = object;
        }
    
        public MyObject getMyObject() {
            return myObject;
        }
    
        public void setMyObject(MyObject myObject) {
            this.myObject = myObject;
        }
        
        @Override
        public void run() {
            super.run();
            myObject.methodF(object);
        }
    
    }

    package chapter2.synch.method;

    public class Run {

        public static void main(String[] args) {
            MyObject myObject = new MyObject();
            Object object = new Object();
            ThreadA threadA = new ThreadA();
            threadA.setObject(object);
            threadA.setMyObject(myObject);
            threadA.setName("A");
            
            ThreadA threadB = new ThreadA();
            threadB.setMyObject(myObject);
            threadB.setObject(object);
            threadB.setName("B");
            
            threadA.start();
            threadB.start();
            
        }
    }

    运行结果:(同步执行)

    begin methodF threadName=A--beginTime:1560937583035
    end methodF threadName=A--endTime:1560937585035
    begin methodF threadName=B--beginTime:1560937585035
    end methodF threadName=B--endTime:1560937587035

    结论:对象锁。

    如果synchronized加到static方法上是给Class类上锁,Class锁可以对类的所有实例对象起作用。

    特点:

    • synchronized关键字拥有锁重入的功能,当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象锁的,否则就死锁了。
    • 当存在父子继承关系时,子类是可以通过“可重入锁”调用父类的同步方法的。
    • 出现异常,锁自动释放。
    • 同步不具有继承性。
  • 相关阅读:
    二测试组织
    如何编写测试计划
    C#三种字符串拼接方法的效率对比
    CSS内容溢出时,显示省略号
    JQuery文件上传控件Uploadify文档
    LINQ to Entities 不识别方法“Boolean Like(System.String, System.String)”,因此该方法无法转换为存储表达式。
    Linux 各目录的作用
    服务器注释事项
    资料:mnist.pkl.gz数据包的下载以及数据内容解释
    RockPaperScissorsLizardSpock Python实现
  • 原文地址:https://www.cnblogs.com/hunter-56213/p/11052921.html
Copyright © 2020-2023  润新知