zoukankan      html  css  js  c++  java
  • 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关键字拥有锁重入的功能,当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象锁的,否则就死锁了。
    • 当存在父子继承关系时,子类是可以通过“可重入锁”调用父类的同步方法的。
    • 出现异常,锁自动释放。
    • 同步不具有继承性。
  • 相关阅读:
    查看文件夹内各文件数目
    Resnet论文翻译
    查看keras自动给文件夹标号
    文件夹内自动图片遍历
    将wiki人脸数据集的性别信息提取出来制作标签
    将wiki人脸数据集中的图片按男女分类
    IPFS私有网络集群搭建
    带参数的函数增加装饰器
    【IPFS + 区块链 系列】 入门篇 — IPFS环境配置
    程序员那些事儿:技术骨干的烦恼
  • 原文地址:https://www.cnblogs.com/hunter-56213/p/11052921.html
Copyright © 2011-2022 走看看