线程安全映射操作

时间:2019-02-14 07:52:37

标签: java hashmap synchronized

我遇到了以下代码,并指出了一些不一致之处-多线程安全代码。

Angular CLI: 1.6.56
Node: 8.9.4
OS: linux x64
Angular: 5.2.1
... animations, common, compiler, compiler-cli, core, forms
... http, platform-browser, platform-browser-dynamic
... platform-server, router

@angular/cdk: 5.1.0
@angular/cli: 1.6.5
@angular/material: 5.1.0
@angular-devkit/build-optimizer: 0.0.41
@angular-devkit/core: 0.0.28
@angular-devkit/schematics: 0.0.51
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.5
@schematics/angular: 0.1.16
typescript: 2.6.2
webpack: 3.10.0
  1. 为什么要在clusterkey上同步地图-它不应该作为监视器本身在地图上同步?
  2. 最后一个用户是否也应该添加...也要同步?
  3. 以线程安全的方式添加单个用户似乎是很多代码。什么是更聪明的实现?

3 个答案:

答案 0 :(得分:4)

这里只是一些观察结果:

  1. Synchronizing on a String is a very bad idea->在clusterKeyserverKey上进行同步可能无法达到预期的效果。
  2. 最好使用ConcurrentHashMapConcurrentHashSet

尽管没有更多背景信息,但实际上不可能回答这个问题。似乎代码编写者希望安全地为每个clusterKeyserverKey创建1个映射,以便只能将用户添加一次。

一种(可能更好)的方法是仅将synchronize上的clusters放在地图本身上,那么您很安全,因为只有一个线程可以读取和/或写入该地图。

另一种方式是使用自定义Lock,也许一个用于读取,另一个用于写入,尽管如果一个线程正在向Map写入而另一个线程正在写入public function new(Request $request){ $user = new Client(); $user->setEnabled(true); $event = new GetResponseUserEvent($user, $request); $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event); if (null !== $event->getResponse()) { return $event->getResponse(); } $form = $this->formFactory->createForm(); $form->setData($user); $form->handleRequest($request); if ($form->isSubmitted()) { if ($form->isValid()) { $event = new FormEvent($form, $request); $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event); $url = $this->generateUrl('fos_user_registration_confirmed'); $response = new RedirectResponse($url); $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response)); return $response; } $event = new FormEvent($form, $request); $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event); if (null !== $response = $event->getResponse()) { return $response; } } return [ 'form' => $form->createView() ]; } ,则可能再次导致不一致。从中读取确切的值。

答案 1 :(得分:2)

代码看起来像Double checked locking idiom的非完整版本,有时用于延迟初始化。阅读提供的链接,了解为什么这是一个非常糟糕的实现。

给定代码的问题是它间歇性地失败。当有多个线程试图使用相同的键(或具有相同哈希码的键)在地图上工作时,存在竞争状态,这意味着第一个创建的地图可能会被第二个哈希图替换。

答案 2 :(得分:1)

1-同步试图避免两个线程同时在该Map中创建新的Entry。第二个必须等待,这样他的(servers==null)也不会返回true

2-该users列表似乎不在范围内,但似乎不需要同步。也许程序员知道没有重复的userId,或者他不在乎一次又一次地重置同一用户。

3- ConcurrentHashMap也许是