简体   繁体   中英

When using static object lock doesn't work?

I'm new at Concurrency, i'm trying to understand synchronized block:

public static int count1 = 0;
public static Object lock1 = new Object();

public static void add(){
        synchronized (lock1) {
            count1++;
        }
}

my problem is with lock1, it doesn't work, when the method starts printing the color, it prints them randomly, so i think the problem is in synchronized block, because i watch some tutorials about this, all of them say the lock object must be static so no interference happens, but here i don't see that, Why?

This is the method that prints the color of each thread:

public static void compute(){
        String color = null;
        switch (Thread.currentThread().getName()) {
            case "First Count Down":
                color = TextColors.ANSI_YELLOW;
                break;
            case "Second Count Down":
                color = TextColors.ANSI_MAGENTA;
                break;
        }
        for (int i=0;i<100;i++) {
            System.out.println(color + Thread.currentThread().getName() + "is Running");
            //add();
            add();
        }
    }

and this is the threads :

public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                compute();
            }
        });
        t1.setName("First Count Down");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                compute();
            }
        });
        t2.setName("Second Count Down");

        t1.start();
        t2.start();

        try{
            t1.join();
            t2.join();

        }catch (InterruptedException io){
            io.printStackTrace();

        }

        System.out.println("Count1 = " + count1 + " Count2 = " + count2);

    }

Sorry if my English is bad, i'm not a native speaker, thanks in advance

First of all, I think now I understand your question. You're trying to print out your lines without interfering with the lines of the other threads.

To achieve this, you have to "protect" the part of your code, which prints out one line, not to get printed out another line at the same time from another thread.

The protection can be done by synchronizing those lines of code.

You are currently synchronizing only the addition to that counter.

Your lock (the object you're locking on, the one and only instance of that new Object()) is static and you do not change it in your code, so it must work.

public static Object lock1 = new Object();

You could make the variable to final to get immutable, but currently that's not the problem. I would recommend that though.

The lock means, that if any other thread is landing in (executing) the same line of code (the beginning of the synchronized block), they won't get execution until the blocking thread is giving up its lock. This is only true, if they holding and asking for the very same lock. And as you're only using the very same new Object() instance, your lock should be okay.

Currently your code is built up that the add() method basically waits until one of the threads is counting up one.

If you want to change it so that you're getting separately printed out lines, try to synchronize the "line printing block" like this:

    synchronized (lock1) {
        System.out.println(color + Thread.currentThread().getName() + "is Running");
        add();
    }

And let the counting not be synchronized.

private static void add(){
    count1++;
}

This would work but mostly you don't want to let your add() method unsynchronized. It could be executed from other threads, who knows. But for your case, those changes would help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM