public class Test { public List<String> lists = Collections .synchronizedList(new ArrayList<String>()); //使用不同的锁策略,导致数据出现混乱 public synchronized boolean listIfAbsent(String str) { boolean ifAbsent = lists.contains(str); if (!ifAbsent) { lists.add(str); } return ifAbsent; } //使用同一个锁策略,保证数据的正确性 public boolean listIfAbsent1(String str) { synchronized (lists) { boolean ifAbsent = lists.contains(str); if (!ifAbsent) { lists.add(str); } return ifAbsent; } } public static void main(String[] args) { final Test t = new Test(); new Thread() { public void run() { //该线程正在对list最修改 if (!t.lists.contains("a")) { t.lists.add("a"); } if (!t.lists.contains("b")) { t.lists.add("b"); } // t.lists.set(0, "chenliang"); System.out.println(t.lists); } }.start(); t.listIfAbsent1("a"); // t.listIfAbsent("b"); } }
从这代码中,我们会发现将线程安全委托给Collections的synronized也是不可行的。
因为他们使用的不同的锁策略,进一步的说就是listIfAbsent方法使用的Test这个对象锁。
而我们无法控制共有的 List<String> lists 不被其他的线程访问,并且进行修改。
所以在写代码的时候一定要考虑清楚,否则会出现很严重的问题。