美文网首页
Java线程同步操作

Java线程同步操作

作者: output | 来源:发表于2018-03-03 13:14 被阅读1次

    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。

    相关文章

      网友评论

          本文标题:Java线程同步操作

          本文链接:https://www.haomeiwen.com/subject/kuptfftx.html