Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: thread unsafe issue of MySQLKeywordChecker initialization #1599

Merged
merged 4 commits into from
Sep 6, 2019

Conversation

chenxi-null
Copy link
Contributor

Performing additional initialization on an object after assignment to a shared variable guarded by double-checked locking is not thread-safe, and could result in unexpected behavior.

Potential race condition: this instance of keywordChecker is available to other threads before keywordSet are assign, which may causes NPE if other threads call '#check' method.

Below is code segment (the code comment is added by me):

private static volatile KeywordChecker keywordChecker = null;
private static volatile Set<String> keywordSet = null;

public static KeywordChecker getInstance() {
    if (keywordChecker == null) {
        synchronized (MySQLKeywordChecker.class) {
            if (keywordChecker == null) {
                keywordChecker = new MySQLKeywordChecker();
                // additional initialization inside double-checked locking is not thread-safe!
                keywordSet = Arrays.stream(MySQLKeyword.values()).map(MySQLKeyword::name).collect(Collectors.toSet());
            }
        }
    }
    return keywordChecker;
}


@Override
public boolean check(String fieldOrTableName) {
    if (keywordSet.contains(fieldOrTableName)) {
        return true;
    }
    if (null != fieldOrTableName) {
        fieldOrTableName = fieldOrTableName.toUpperCase();
    }
    return keywordSet.contains(fieldOrTableName);

}

Since MySQLKeywordChecker is singleton, the field keywordSet doesn't need to be static,
the initialization of keywordSet can be moved to constructor, removing the additional initialization inside locking, which ensures thread safely.

Potential race condition: this instance of `keywordChecker` is available to other threads before `keywordSet` are assign, which may causes NPE if other threads call '#check' method.

Since `MySQLKeywordChecker` is singleton, the field `keywordSet` doesn't need to be static,
the initialization of `keywordSet` can be moved to constructor, removing the additional initialization inside locking,
   which ensures thread safely.
@codecov-io
Copy link

codecov-io commented Sep 6, 2019

Codecov Report

Merging #1599 into develop will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@              Coverage Diff              @@
##             develop    #1599      +/-   ##
=============================================
+ Coverage      46.43%   46.43%   +<.01%     
- Complexity      1713     1714       +1     
=============================================
  Files            350      350              
  Lines          12827    12828       +1     
  Branches        1615     1615              
=============================================
+ Hits            5956     5957       +1     
  Misses          6224     6224              
  Partials         647      647
Impacted Files Coverage Δ Complexity Δ
...source/undo/mysql/keyword/MySQLKeywordChecker.java 98.58% <100%> (ø) 7 <0> (+1) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0398ba2...d354ac9. Read the comment docs.

@xingfudeshi xingfudeshi self-requested a review September 6, 2019 07:44
Copy link
Member

@xingfudeshi xingfudeshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good!LGTM.

Copy link
Contributor

@zjinlei zjinlei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! LGTM

@zjinlei zjinlei changed the title Fix thread unsafe issue of initialization of MySQLKeywordChecker bugfix: thread unsafe issue of initialization of MySQLKeywordChecker Sep 6, 2019
@zjinlei zjinlei changed the title bugfix: thread unsafe issue of initialization of MySQLKeywordChecker bugfix: thread unsafe issue of MySQLKeywordChecker initialization Sep 6, 2019
@zjinlei zjinlei merged commit e91edf4 into apache:develop Sep 6, 2019
@wangliang181230 wangliang181230 added this to the 0.8.1 milestone Aug 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants