concurrency bug patterns for multicore systems

1. An antipattern from Jetty

volatile 변수를 쓸 데 없는 곳에 사용하지 마라, Optimization에 관련된 필드 선언이기 때문에 잘 모르면 쓰지 말고, java.util.concurrent 패키지의 AtomicXX 클래스를 사용해라 .

2. Synchronization on mutable fields

변하지 않는 객체로만 동기화 객체로 써라, 객체의 인스턴스가 여러 개로 나누어지면 동기화를 보장할 수 있다. 동기화는 인스턴스 단위이다.

3. java.util.concurrent lock leak
java.util.concurrent.Lock 사용시에는 finally로 반드시 lock을 처리한다.
Lock의 생성과 해지를 늘 기억해라. 이런 게 귀찮다고 생각하지 말자. c/c++은 끔직했다...

4. Performance tuning synchronized blocks
동기화 블럭은 최소단위로 써라

5. Multi-stage access
상황에 잘 맞게 써야 하는데, 무조건 이렇게 바꾸라는 것은 아니다.
thread-safe한 메소드를 잘 구현하고 싶을 때, 클래스안의 변수는 동기화 타입(ConcurrentHashMap)이긴 하지만, return 또는 선언하는 곳에서 문제가 될 수 있다. 
무조건 동기화 변수만 쓴다고 해서 모든 곳에서 다 동기화가 이루어진다고 생각하지 말자.

6. Symmetric lock deadlock
중첩으로 동기코드를 작성시에는 순서를 잘 고려하면서 사용해야 한다.

기술지원하다보면, 사람들은 가끔씩 3, 5번 정도가 조금 걸리는 것 같다.
요즘에 framework가 thread-safe한 인스턴스 기반이라서 framework 기반이 아닐 때만 이슈인듯.. 지금은 framework을 쓰다보니.. 문제는 생기지는 않지만, frameowork없이 개발을 못한다는 한계가 있다.

Posted by 김용환 '김용환'

어디서 문제가 되었나 했더니..
아파치 루씬/Solr 쪽에서 테스트하다가 문제 발견되었다.
jdk7 뿐 아니라 jdk6 에서도 영향이 있을 수 있으니. 조심히 jvm option 체크할 것!
(아래 빨강 색칠)

From: Uwe Schindler
Date: Thu, 28 Jul 2011 23:13:36 +0200
Subject: [WARNING] Index corruption and crashes in Apache Lucene Core / Apache Solr with Java 7

Hello Apache Lucene & Apache Solr users,
Hello users of other Java-based Apache projects,

Oracle released Java 7 today. Unfortunately it contains hotspot compiler
optimizations, which miscompile some loops. This can affect code of several
Apache projects. Sometimes JVMs only crash, but in several cases, results
calculated can be incorrect, leading to bugs in applications (see Hotspot
bugs 7070134 [1], 7044738 [2], 7068051 [3]).

Apache Lucene Core and Apache Solr are two Apache projects, which are
affected by these bugs, namely all versions released until today. Solr users
with the default configuration will have Java crashing with SIGSEGV as soon
as they start to index documents, as one affected part is the well-known
Porter stemmer (see LUCENE-3335 [4]). Other loops in Lucene may be
miscompiled, too, leading to index corruption (especially on Lucene trunk
with pulsing codec; other loops may be affected, too – LUCENE-3346 [5]).

These problems were detected only 5 days before the official Java 7 release,
so Oracle had no time to fix those bugs, affecting also many more
applications. In response to our questions, they proposed to include the
fixes into service release u2 (eventually into service release u1, see [6]).
This means you cannot use Apache Lucene/Solr with Java 7 releases before
Update 2! If you do, please don’t open bug reports, it is not the
committers’ fault! At least disable loop optimizations using the
-XX:-UseLoopPredicate JVM option to not risk index corruptions.

Please note: Also Java 6 users are affected, if they use one of those JVM
options, which are not enabled by default: -XX:+OptimizeStringConcat or

It is strongly recommended not to use any hotspot optimization switches in
any Java version without extensive testing!

In case you upgrade to Java 7, remember that you may have to reindex, as the
unicode version shipped with Java 7 changed and tokenization behaves
differently (e.g. lowercasing). For more information, read
JRE_VERSION_MIGRATION.txt in your distribution package!

On behalf of the Lucene project,


Posted by 김용환 '김용환'
TAG Bug, jdk7
java7 RC 버그로 의심되는 코드가 있었다.

c:\test 라는 디렉토리를 계속 모니터링하고, 디렉토리안에서 특정 폴더나 파일이 변경되면 알려주는 간단한 코드이다.

import java.nio.channels.CompletionHandler;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import static java.nio.file.StandardWatchEventKinds.*;
public class WatchServiceTest {
 public static void main(String[] args) throws Exception {
  Path dir = Paths.get("c:\\test\\");
  WatchService watcher = FileSystems.getDefault().newWatchService();
  WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE,
  for (;;) {
   key = watcher.take();
   for (WatchEvent<?> event : key.pollEvents()) {
    if (event.kind() == ENTRY_CREATE) {
     Path name = (Path) event.context();
     System.out.println("path : " + name.toAbsolutePath());
     System.out.format("%s created%n", name);
    } else if (event.kind() == ENTRY_DELETE) {
     Path name = (Path) event.context();
     System.out.println("path : " + name.toAbsolutePath());
     System.out.format("%s deleted%n", name);
    } else if (event.kind() == ENTRY_MODIFY) {
     Path name = (Path) event.context();
     System.out.println("path : " + name.toAbsolutePath());
     System.out.format("%s modified%n", name);

c:\test\ 에서 폴더를 생성했는데.. 잉??
workspace 에서 폴더를 생성했다고 나온다..

WatchEvent 클래스의 context 메소드를 호출하면 Path 가 나오는데, 내부적으로 꼬였나 보다.

path : E:\jdk1.7\test\새 폴더
새 폴더 created
path : E:\jdk1.7\test\새 폴더 (2)
새 폴더 (2) created
path : E:\jdk1.7\test\새 폴더 (2)
새 폴더 (2) deleted
path : E:\jdk1.7\test\make
make created

관련해서 Oracle BugDatabase에 신고했다.

Posted by 김용환 '김용환'
TAG Bug, java7

jdk 19에서 아래와 같은 문제가 밸생할 수 있다.
algorithm check failed: MD2withRSA is disabled

토의 내용

Bug ID: 6948803
Votes 0
Synopsis CertPath validation regression caused by SHA1 replacement root and MD2 disable feature
Category java:classes_security
Reported Against
Release Fixed 6u21(b05), 7(b97) (Bug ID:2193256)
State 10-Fix Delivered, bug
Priority: 2-High
Related Bugs 6861062 , 6904162 , 2194455 , 7017668
Submit Date 30-APR-2010
In 6u19, several VeriSign MD2/MD5 root certificates were replaced with stronger SHA1 versions (same key, stronger signature). Some customers using certificates issued from the VeriSign PCA 3 root have been reporting problems that cause their existing certificate chains to be rejected by the JRE because the certificate chain still includes the weaker MD2 root and we disabled MD2 support in 6u17.

The problem is that our certpath validation implementation adds the SHA1 root to the beginning of the chain but does not replace the existing MD2 root. So the chain includes both roots, first the SHA1, then the MD2 and then the rest of the chain. The chain is rejected because the MD2 root is treated as an intermediate CA cert. 

It seems our implementation should instead replace the MD2 root with the stronger SHA1 root before validating the chain.
Posted Date : 2010-04-30 13:38:51.0
Work Around
Their are a few ways to workaround the issue. For TLS, the server's certificate chain can be reconfigured so that either the MD2 root certificate is not included in the chain (including the root cert is optional in TLS), or it should be replaced with the SHA1 root certificate.

For code signing, you can re-sign the jar and include a chain with the SHA1 root instead of the MD2 root, or a chain without the root cert.
Fixed. A cert with the same issuer and public key as a trusted anchor is removed from the chain.
Posted Date : 2010-05-18 10:43:09.0
  Include a link with my name & email   

PLEASE NOTE: JDK6 is formerly known as Project Mustang

oracle java 6 update 21에서 패치되었다.
6948803  java classes_security CertPath validation regression caused by SHA1 replacement root and MD2 disable feature

Posted by 김용환 '김용환'
TAG Bug, Java