• 多线程 synchronized关键字


     在多线程情况下,当多个线程操作同一个资源的时候,会出现安全问题,例如脏读(一个线程咋读取变量的时候,值已经被另一个线程改变)。

    synchronized关键字:可用来同步方法或者代码块。有关synchronized,总结一下几条。

      1 synchronized关键字锁的是对象,当多个对象会创建多个锁,而达不到同步的效果。

      2 只有操作公共资源的时候才需要上锁,非公共资源没必要上锁。

      3 synchronized关键字拥有可重入锁。

      4 异常出现的时候,会自动释放锁。

      5 同步不具备继承性。

      6 sleep()方法不会释放锁。

      7wait()方法会释放锁。

      8 synchronized可同步方法,也可以同步代码块。

    下面对其中几条进行验证;

    方法类:

    public class MyMethod {
    
    	
    	synchronized public void methodA(String username) throws InterruptedException{
    		System.out.println(username);
    		if(username.equals("a")){
    			
    			System.out.println(Thread.currentThread().getName()+"  into methodA");
    			Thread.sleep(2000);
    			System.out.println(Thread.currentThread().getName()+"  out methodA");
    		}
    		else {
    			System.out.println(Thread.currentThread().getName()+"  into methodB");
    			Thread.sleep(1000);
    			System.out.println(Thread.currentThread().getName()+"  out methodB");
    		}
    		/*while(true){
    			
    		}*/
    	}
    	//synchronized 锁代码块
    	public static void methodB(String lock) throws InterruptedException{
    		synchronized (lock) {
    			System.out.println(Thread.currentThread().getName()+"  into lock");
    			Thread.sleep(1000);
    			System.out.println(Thread.currentThread().getName()+"  out lock");
    			
    		}
    	}
    }
    

      

    主线程:synchronized同步代码块。synchronized(this)锁的是当前对象。

    public class Run {
    
    	public static void main(String[] args) throws InterruptedException {
    		
    		MyMethod m1=new MyMethod();
    		MyMethod m2=new MyMethod();
    		String lock="";
    		Thread t1 =new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					m1.methodB(lock);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		},"t1");
    		Thread t2 =new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					m1.methodB(lock);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		},"t2");
    		t1.start();
    		t2.start();
    
    	}
    
    }
    

      控制台:

    t2  into lock
    t2  out lock
    t1  into lock
    t1  out lock
    

      synchronized同步方法,修改主线程如下

    public class Run {
    
    	public static void main(String[] args) throws InterruptedException {
    		
    		MyMethod m1=new MyMethod();
    		MyMethod m2=new MyMethod();
    		String lock="";
    		Thread t1 =new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					m1.methodA("a");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		},"t1");
    		Thread t2 =new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					m1.methodA("b");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		},"t2");
    		t1.start();
    		t2.start();
    
    	}
    
    }
    

      控制台输出:

    b
    t2  into methodB
    t2  out methodB
    a
    t1  into methodA
    t1  out methodA
    

      可以发现达到同步的效果。

       再次修改主线程代码如下:

    public class Run {
    
    	public static void main(String[] args) throws InterruptedException {
    		
    		MyMethod m1=new MyMethod();
    		MyMethod m2=new MyMethod();
    		String lock="";
    		Thread t1 =new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					m1.methodA("a");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		},"t1");
    		Thread t2 =new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					m2.methodA("b");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		},"t2");
    		t1.start();
    		t2.start();
    
    	}
    
    }
    

      控制台如下

    b
    a
    t1  into methodA
    t2  into methodB
    t2  out methodB
    t1  out methodA
    

      并且多次执行main方法,发现控制台打印顺序不同。此处调用的是两个对象,所以jvm会创建两个锁,互不影响,所以在锁,只能锁一个对象中的方法。证明synchronized锁的是对象。此过程中,我还测试了静态方法,当把methodA()方法改为静态的时候

    两个对象一样会有同步的效果。

    可重入锁概念:自己可以再次获取自己的内部锁。如有一个线程获得了某个对象的锁,此时这个对象还没有释放,当其再次想获取这个对象的锁的时候,还是可以获取的,否则会造成死锁。

      

      每一个优秀的人,都有一段沉默的时光。不抱怨,不诉苦,最后度过那段感动自己的日子。

  • 相关阅读:
    XNA中的中文输入(三)
    0.033秒的艺术 测试程序性能
    0.033秒的艺术 List.Sort以及快速排序
    从Demo到Engine(二) Render Queue Sort
    Bounding Volume Performance Test:AABB vs OBB vs Sphere
    0.033秒的艺术 Radix Sort
    从Demo到Engine(一) IRenderable
    0.033秒的艺术 for vs. foreach
    XNA中的中文输入(一)
    0.033秒的艺术 XNA数学库中的陷阱
  • 原文地址:https://www.cnblogs.com/hrlizhi/p/9409285.html
Copyright © 2020-2023  润新知