public void put(String key, String val) throws IllegalArgumentException {
    if (key == null) {
      throw new IllegalArgumentException("key cannot be null");
    }

    Map<String, String> oldMap = copyOnThreadLocal.get();
    Integer lastOp = getAndSetLastOperation(WRITE_OPERATION);

    if (wasLastOpReadOrNull(lastOp) || oldMap == null) {
      Map<String, String> newMap = duplicateAndInsertNewMap(oldMap);
      newMap.put(key, val);
    } else {
      oldMap.put(key, val);
    }
  }
@Test
  public void nearSimultaneousPutsShouldNotCauseConcurrentModificationException() throws InterruptedException {
    // For the weirdest reason, modifications to mdcAdapter must be done
    // before the definition anonymous ChildThread class below. Otherwise, the
    // map in the child thread, the one contained in mdcAdapter.copyOnInheritThreadLocal,
    // is null. How strange is that?

    // let the map have lots of elements so that copying it takes time
     for (int i = 0; i < 2048; i++) {
      mdcAdapter.put("k" + i, "v" + i);
    }

    ChildThread childThread = new ChildThread(mdcAdapter, null, null) {
      @Override
      public void run() {
        for (int i = 0; i < 16; i++) {
          mdcAdapter.put("ck" + i, "cv" + i);
          Thread.yield();
        }
        successful = true;
      }
    };


    childThread.start();
    Thread.sleep(1);
    for (int i = 0; i < 16; i++) {
      mdcAdapter.put("K" + i, "V" + i);
    }
    childThread.join();
    assertTrue(childThread.successful);
  }