On Sat, 9 Oct 2021 15:49:01 GMT, liach <d...@openjdk.java.net> wrote:

> You should really post your changes to jdk-dev at openjdk.java.net before 
> submitting these so you can know if a change is potentially good or bad. 
> Since jdk pull requests require issue numbers, you can ask people on the list 
> if this is a good idea; if it is, someone on the list may create an issue for 
> you, which probably means your suggestion is valid, and only then you should 
> send a pull request.

you mean I should pin the patch file at mailing list first? Get it.

I just think it easier to view the code changes at github pr page than the 
patch file...but if the workflow should be asking at the mailing list first, 
then I will obey.

> src/java.base/share/classes/java/io/InputStream.java line 550:
> 
>> 548: 
>> 549:         if ((skipBuffer == null) || (skipBuffer.length < size)) {
>> 550:             skipBuffer = new byte[size];
> 
> In the `Reader` class, `skipBuffer` access is thread-safe as it's behind a 
> synchronization on the `lock`. This one isn't and is subject to weird java 
> memory models: in extreme cases, if the `skipBuffer` is set to non-null on 
> another thread, it may be non-null on first field read and null on second 
> field read.
> 
> Hence you should write code like this instead:
> 
>         byte[] skipBuffer = this.skipBuffer;
>         if ((skipBuffer == null) || (skipBuffer.length < size)) {
>             this.skipBuffer = skipBuffer = new byte[size];
>         }
> 
> so you only read the field once and get consistent results.

> In the `Reader` class, `skipBuffer` access is thread-safe as it's behind a 
> synchronization on the `lock`. This one isn't and is subject to weird java 
> memory models: in extreme cases, if the `skipBuffer` is set to non-null on 
> another thread, it may be non-null on first field read and null on second 
> field read.
> 
> Hence you should write code like this instead:
> 
> ```java
>         byte[] skipBuffer = this.skipBuffer;
>         if ((skipBuffer == null) || (skipBuffer.length < size)) {
>             this.skipBuffer = skipBuffer = new byte[size];
>         }
> ```
> 
> so you only read the field once and get consistent results.

@liach

sorry for missing considering about multi-thread situations...
...the question you bring are correct, but maybe this is not that easy to solve.


        byte[] skipBuffer = this.skipBuffer;
        if ((skipBuffer == null) || (skipBuffer.length < size)) {
            this.skipBuffer = skipBuffer = new byte[size];
        }


this solution might also bring another problem:

first, this.skipBuffer = byte[3]

then, Thread A call skip(10)

meanwhile Thread B call skip(6)

in extream situation, when doing `this.skipBuffer = skipBuffer` in Thread B, it 
might make this.skipBuffer to a byte[6] in thread A, and thus cause a 
IndexOutofBoundException in Thread A.

So only way to do it safely seems adding some lock like in Reader... that is 
pretty costy, I don't think it worth...

closed.

-------------

PR: https://git.openjdk.java.net/jdk/pull/5872

Reply via email to