zoukankan      html  css  js  c++  java
  • Java线程同步操作

    synchronized

    作用于对象实例:对给定对象加锁,进入同步代码前要获得给定对象的锁。

    作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。

    作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

    使用

    给实例对象加锁

    public class AccountingSync implements Runnable {
    	static AccountingSync instance = new AccountingSync();
    	static int i = 0;
    
    	@Override
    	public void run() {
    		for (int k = 0; k < 10000; k++) {
    			synchronized (instance) {
    				i++;
    			}
    		}
    	}
    
    	@Test
    	public void testInteger() throws InterruptedException {
    		int count = 10;
    		Thread[] ts = new Thread[count];
    
    		for (int k = 0; k < count; k++) {
    			ts[k] = new Thread(instance);
    		}
    
    		// start
    		for (int k = 0; k < count; k++) {
    			ts[k].start();
    		}
    
    		// join
    		for (int k = 0; k < count; k++) {
    			ts[k].join();
    		}
    
    		System.out.println(i);
    	}
    }
    

    给类方法加锁

    public class AccountingSync2 implements Runnable {
    	static AccountingSync2 instance = new AccountingSync2();
    	static int i = 0;
    
    	public synchronized void increase() {
    		i++;
    	}
    
    	@Override
    	public void run() {
    		for (int k = 0; k < 10000; k++) {
    			increase();
    		}
    	}
    
    	@Test
    	public void testInteger() throws InterruptedException {
    		int count = 10;
    		Thread[] ts = new Thread[count];
    
    		for (int k = 0; k < count; k++) {
    			ts[k] = new Thread(instance);
    		}
    
    		// start
    		for (int k = 0; k < count; k++) {
    			ts[k].start();
    		}
    
    		// join
    		for (int k = 0; k < count; k++) {
    			ts[k].join();
    		}
    
    		System.out.println(i);
    	}
    }
    

    给类方法加锁的错误演示

    public class AccountingSyncBad implements Runnable {
    	static int i = 0;
    
    	public synchronized void increase() {
    		i++;
    	}
    
    	@Override
    	public void run() {
    		for (int k = 0; k < 10000; k++) {
    			increase();
    		}
    	}
    
    	@Test
    	public void testInteger() throws InterruptedException {
    		int count = 10;
    		Thread[] ts = new Thread[count];
    
    		for (int k = 0; k < count; k++) {
    			ts[k] = new Thread(new AccountingSyncBad());
    		}
    
    		// start
    		for (int k = 0; k < count; k++) {
    			ts[k].start();
    		}
    
    		// join
    		for (int k = 0; k < count; k++) {
    			ts[k].join();
    		}
    
    		System.out.println(i);
    	}
    }
    

    假设把给类实例加锁中的每个实例比作一个门,上面的测试方法中每个门都有锁但是10个门10把锁,每个线程进一个门。还是不能保证临界区资源i同时只一个线程访问

    fix

    @Test
    public void testIntegerFix() throws InterruptedException {
      int count = 10;
      AccountingSyncBad instance = new AccountingSyncBad();
      Thread[] ts = new Thread[count];
    
      for (int k = 0; k < count; k++) {
        ts[k] = new Thread(instance);
      }
    
      // start
      for (int k = 0; k < count; k++) {
        ts[k].start();
      }
    
      // join
      for (int k = 0; k < count; k++) {
        ts[k].join();
      }
    
      System.out.println(i);
    }
    

    给静态类方法加锁

    public class AccountingSyncClass implements Runnable {
    	static int i = 0;
    
    	public static synchronized void increase() {
    		i++;
    	}
    
    	@Override
    	public void run() {
    		for (int k = 0; k < 10000; k++) {
    			increase();
    		}
    	}
    
    	@Test
    	public void testInteger() throws InterruptedException {
    		int count = 10;
    		Thread[] ts = new Thread[count];
    
    		for (int k = 0; k < count; k++) {
    			ts[k] = new Thread(new AccountingSyncClass());
    		}
    
    		// start
    		for (int k = 0; k < count; k++) {
    			ts[k].start();
    		}
    
    		// join
    		for (int k = 0; k < count; k++) {
    			ts[k].join();
    		}
    
    		System.out.println(i);
    	}
    	
    	@Test
    	public void testIntegerFix() throws InterruptedException {
    		int count = 10;
    		AccountingSyncClass instance = new AccountingSyncClass();
    		Thread[] ts = new Thread[count];
    
    		for (int k = 0; k < count; k++) {
    			ts[k] = new Thread(instance);
    		}
    
    		// start
    		for (int k = 0; k < count; k++) {
    			ts[k].start();
    		}
    
    		// join
    		for (int k = 0; k < count; k++) {
    			ts[k].join();
    		}
    
    		System.out.println(i);
    	}
    }
    

    上面测试的testInteger方法和testIntegerFix方法都能得到正确的结果,原因是给静态类方法加锁相当于10个门用的同一把锁,保证了同一时间只有一个线程能访问临界区资源i。

  • 相关阅读:
    输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
    输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
    输入一个链表,反转链表后,输出链表的所有元素。java实现
    少一点虚荣,多一点务实
    Mysql存储引擎__笔记
    osi七层模型和两主机传输过程:
    redis_笔记
    zookeeper_笔记
    rest和soap_笔记
  • 原文地址:https://www.cnblogs.com/okokabcd/p/8496417.html
Copyright © 2011-2022 走看看