Java同步以避免ConcurrentModificationExceptions?

Azi*_*uth 0 java synchronization

我很难让我的程序正常工作.简而言之,我的程序包含几个初始线程:Main,MessageReceiver,Scheduler(使用Quartz包)和Scheduler线程调度的两种类型的线程:TraceReader和ScheduledEvent.现在,当触发TraceReader时,它会读取一个特殊的跟踪文件,并按开始时间,重复间隔(500毫秒到1秒)和结束时间来安排事件.目前,可以安排大约140个事件同时触发,这会导致大量的ConcurrentModificationException错误.现在一些代码:

public class Client { //main class
 public static volatile HashMap<Integer, Request> requests;
 public static class Request{
    String node;
    int file_id;
    long sbyte;
    int length;
    int pc_id;
    public Request(){

    }
 }

 public static synchronized void insertRequest(int req_nr, String node, int file_id, long sbyte, int length, int pc_id) {
    Request tempr = new Request();
    tempr.node = node;
    tempr.file_id = file_id;
    tempr.sbyte = sbyte;
    tempr.length = length;
    tempr.pc_id = pc_id;
    requests.put(req_nr, tempr);                       
 }

public static synchronized void doSynchronized(int req_nr, String node, int file_id, long sbyte, int length, int pc_id) {        
    reqnr++;
    String r = "P" + reqnr + "," + file_id + "," + Long.toString(sbyte) + "," + length;        
    insertRequest(Client.reqnr, node, file_id, sbyte, length, pc_id);        
}

public class ScheduledEvent implements Job {
 public synchronized boolean isRequested(long sbyte, int length, int file_id, String node) {
    Request req;
    Iterator<Integer> it = Client.requests.keySet().iterator();
    while (it.hasNext()) {
        req = Client.requests.get(it.next());
        if (req.node.equals(node) && req.file_id == file_id && hits(req.sbyte, req.length, sbyte, length)) {
            return true;
        }
    }
    return false;
 }  
}
Run Code Online (Sandbox Code Playgroud)

所以我基本上得到了ScheduledEvent类的isRequested方法的错误.由于有超过100个并发线程,我认为由于其他线程正在使用Client.doSynchronized()而其他线程尝试在isRequested方法中迭代请求对象而导致的错误.有没有办法让线程访问该对象同步而不使用阻塞(Thread.join()等)?

Zed*_*Zed 5

代码的基本问题是对象在不同对象(锁)上同步.要解决这个问题,不要声明同步的方法 - 在类的对象上进行同步 - 而是在请求对象本身上进行同步:

public class Client { //main class

 public static void insertRequest(int req_nr, String node, int file_id, long sbyte, int length, int pc_id) {
    ...
    synchronized (requests) {
      requests.put(req_nr, tempr);
    }
    ...
 }

public class ScheduledEvent implements Job {
 public boolean isRequested(long sbyte, int length, int file_id, String node) {
    ...
    synchronized (requests) {
      while (it.hasNext()) {
          req = Client.requests.get(it.next());
          if (req.node.equals(node) && req.file_id == file_id && hits(req.sbyte,   req.length, sbyte, length)) {
            return true;
        }
      }
    }
    ...
 }  
}
Run Code Online (Sandbox Code Playgroud)