java 多线程同步块不工作

java multithreading synchronized block not working

我不明白为什么我在以下代码中出现异常:class 级别锁定以及对象级别锁定:

似乎对象级锁定应该在这里工作,因为我们正在使用不同的线程更改和访问 hm(Object) 值,但我们仍然得到 exception(java.util.ConcurrentModificationException).

我尝试在代码中注释所有三个锁定。

我知道使用 HashtableConcurrentHashMap 我们可以解决这个问题,但是 我想知道使用 HashMap 缺少的概念.

import java.util.HashMap;
class A{
    StringBuilder str = new StringBuilder("ABCD");
    StringBuilder exception = new StringBuilder("");
    HashMap hm = new HashMap();
    public void change() {
        //synchronized(A.class) {
        //synchronized (this){
        synchronized (hm){
            (this.str).append(Thread.currentThread().getName().toString());
            System.out.println(Thread.currentThread().getName()+"::::::"+str);
            hm.put(Thread.currentThread(), Thread.currentThread());
        }
    }
    public void impact() {
        //synchronized(A.class) {
        //synchronized(this) {
        synchronized(hm) {
            System.out.println(Thread.currentThread()+"...Inside impact :::"+hm.get(Thread.currentThread()));
        }
    }
    public void print() {
        System.out.println("Inside print :::"+str);
        System.out.println("Inside print :::exception--"+exception);
    }
}
class B extends Thread{
    A a;
    B(A a){
        this.a=a;
    }
    public void run() {
        try {
            System.out.println("Inside B run::"+a.hm);
            a.change();
            a.impact();
        }
        catch(Exception e){
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            System.out.println(sw.toString());
            a.exception.append(sw.toString());
            try {
                sw.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}

class C extends Thread{
    A a;
    C(A a){
        this.a=a;
    }
    public void run() {
    try {
        System.out.println("Inside C run::"+a.hm);
        a.change();
        a.impact();
    }
    catch(Exception e){
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        System.out.println(sw.toString());
        a.exception.append(sw.toString());
        try {
            sw.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
    }
}
public class multiTest {
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    A a = new A();
    for(int i=0;i<=100;i++) {
        B b = new B(a);
        C c = new C(a);
        b.start();
        c.start();
    }
    try {
        Thread.currentThread().sleep(5000);
    }catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
        a.print();  
    }
}

问题出在这一行:

System.out.println("Inside B run::"+a.hm);

这里有偷偷摸摸的隐式调用 a.hm.toString(),这会偷偷摸摸地迭代地图的条目;但是你没有同步任何东西,所以你没有对 hashmap 的独占访问权。

放在同步块中:

synchronized (a.hm) {
  System.out.println("Inside B run::"+a.hm);
}

(并使 hm 最终化;并且不使用原始类型)。