zoukankan      html  css  js  c++  java
  • 多线程 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()方法改为静态的时候

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

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

      

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

  • 相关阅读:
    LeetCode 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/hrlizhi/p/9409285.html
Copyright © 2011-2022 走看看