Getting object lock with synchronized method

This question already has an answer here:

  • What does 'synchronized' mean? 15 answers
  • Is there an advantage to use a Synchronized Method instead of a Synchronized Block? 22 answers
  • Java synchronized method lock on object, or method? 10 answers

  • This usage of the synchronized keyword causes the method to acquire a lock on the object that the method is being invoked on. Since you have 5 MultiThr objects, that's 5 different objects that are being locked.

    There are a number of options to fix this, for instance you could create an object that to be shared among all MultiThr objects:

    public class MultiThr implements Runnable{
        private static final Object lock = new Object();
    
        public static void main(String[] args) {
            for(int i = 0;i < 5;i++){
                new Thread(new MultiThr()).start();
            }
        }
    
        @Override
        public void run() {
            increment();
        }
    
        public void increment(){
            synchronized (lock) {
                for(int i=0;i<10;i++){
                    System.out.println(i);
                    try {
                        Thread.sleep(400);
                    } catch (InterruptedException e) {}
                }
            }
        }
    }
    

    your increment() method is synchronized. Your problem is that it is a part of your Runnable. More of that, your counter variable i is a local variable, so each thread will have it's own copy of i even without the synchronized keyword. What I would recommend you to do is to create a class MyConter like:

    class MyCounter {   
    
        private int i;
    
        public MyCounter () {
            i = 0;
        }
    
        public int getCounter() {
            return i;
        }
    
        public void increment() {
            i++;
        }
    }
    

    Then pass it as an argument to the MultiThr constructor:

    public class MultiThr implements Runnable{
    
        private MyCounter counter;
    
        public MultiThr(MyCounter counter)  {
            this.counter = counter;
        }
    
        @Override
        public void run() {  
            increment();
        }
    
        public synchronized void increment(){
            for(int i=0;i<10;i++){
                counter.increment();
                System.out.println(counter.getCounter());
                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {
                    // Do not do just e.printStackTrace()
                    Thread.currentThread().interrupt()
                }
            }
        }
    
        public static void main(String[] args) {
            for(int i = 0;i < 5;i++){
               new Thread(new MultiThr()).start();
            }
        }
    }
    

    Or you can use AtomicInteger instead of MyCounter, just make sure that the same instance is passed to each thread.

    链接地址: http://www.djcxy.com/p/91860.html

    上一篇: 线程安全与同步

    下一篇: 使用同步方法获取对象锁定