[ 
https://issues.apache.org/jira/browse/ZOOKEEPER-3652?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17041741#comment-17041741
 ] 

maoling commented on ZOOKEEPER-3652:
------------------------------------

_*--->the value of {{state}} changes over time. Which means that the object on 
which we synchronize may not always be the same, thus defeating the purpose of 
using synchronization to coordinate access between*_ *threads**.*

I write an example to check this. Yes, I can read *Thread name:A-thread, the 
state is:B*
{code:java}
public class EnumTest {

    static volatile States state = States.C;

    static Object object = new Object();

    public enum States {
        A,
        B,
        C;
    }

    public static void main(String[] args) {

        Thread a = new MyThreadA("A-thread");
        a.start();

        Thread b = new MyThreadB("B-thread");
        b.start();
    }

    static class MyThreadB extends Thread {

        private String name;

        public MyThreadB(String name) {
            this.name = name;
        }

        Random r = new Random(1);
        @Override
        public void run() {
            while (true) {
                synchronized (state) {
                    state = States.B;
                    try {
                        TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread name:" + name + ", the state 
is:" + state);
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class MyThreadA extends Thread {

        private String name;

        public MyThreadA(String name) {
            this.name = name;
        }

        Random r = new Random(1);
        @Override
        public void run() {
            while (true) {
                synchronized (state) {
                    state = States.A;
                    try {
                        TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread name:" + name + ", the state 
is:" + state);
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
{code}
[~sylvain] 

Could you please help us improve this?

Zookeeper uses the github workflow. The contributor guideline
 is 
[here](https://cwiki.apache.org/confluence/display/ZOOKEEPER/HowToContribute])

> Improper synchronization in ClientCnxn
> --------------------------------------
>
>                 Key: ZOOKEEPER-3652
>                 URL: https://issues.apache.org/jira/browse/ZOOKEEPER-3652
>             Project: ZooKeeper
>          Issue Type: Bug
>          Components: java client
>    Affects Versions: 3.5.6
>            Reporter: Sylvain Wallez
>            Priority: Major
>
> ZOOKEEPER-2111 introduced {{synchronized(state)}} statements in 
> {{ClientCnxn}} and {{ClientCnxn.SendThread}} to coordinate insertion in 
> {{outgoingQueue}} and draining it when the client connection isn't alive.
> There are several issues with this approach:
>  - the value of the {{state}} field is not stable, meaning we don't always 
> synchronize on the same object.
>  - the {{state}} field is an enum value, which are global objects. So in an 
> application with several ZooKeeper clients connected to different servers, 
> this causes some contention between clients.
> An easy fix is change those {{synchronized(state)}} statements to 
> {{synchronized(outgoingQueue)}} since it is local to each client and is what 
> we want to coordinate.
> I'll be happy to prepare a PR with the above change if this is deemed to be 
> the correct way to fix it.
>  
> Another issue that makes contention worse is 
> {{ClientCnxnSocketNIO.cleanup()}} that is called from within the above 
> synchronized block and contains {{Thread.sleep(100)}}. Why is this sleep 
> statement needed, and can we remove it?
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to