并发访问时树图中的重复键
Duplicated keys in Tree Map when accesing concurrently
谁能找出这段代码中的并发错误?该代码对于一个线程来说工作得很好,但是一旦我同时启动 2 个线程并调用 addScore 方法,它就会向树 Map 添加重复项。
覆盖了compareTO的pojo如下:
public final class UserHighScore implements Comparable<UserHighScore>{
private final int userId;
private final int value;
public UserHighScore(int userId, int value) {
this.userId = userId;
this.value = value;
}
public int getUserId() {
return userId;
}
public int getValue() {
return value;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof UserHighScore)) {
return false;
}
UserHighScore userHighScore = (UserHighScore) obj;
return userHighScore.userId==userId;
}
@Override
public int compareTo(UserHighScore uh) {
if(uh.getUserId()==this.getUserId()) return 0;
if(uh.getValue()>this.getValue()) return 1;
return -1;
}
}
这是我用来模拟用户发出请求的代码:
class User implements Runnable
{
private ScoreServiceImpl scoreService=ScoreServiceImpl.getInstance();
CountDownLatch latch;
public User(CountDownLatch latch)
{
this.latch = latch;
}
@Override
public void run() {
for(int i=0;i<5;i++) {
scoreService.addScore(3,Integer.parseInt(Thread.currentThread().getName()),ThreadLocalRandom.current().nextInt(50000));
}
System.out.println(scoreService.getHighScoreList(3));
}
}
创建线程的主要方法是:
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(RestclientApplication.class, args);
CountDownLatch latch = new CountDownLatch(1);
User user1=new User(latch);
User user2=new User(latch);
Thread t1=new Thread(user1);
Thread t2=new Thread(user2);
t1.setName("1");
t2.setName("2");
t1.start();
t2.start();
//latch.countDown();
}
你的 compareTo 很古怪。你可以用这样的单线程获得相同的结果
ScoreServiceImpl.getInstance().addScore(0,1,4);
ScoreServiceImpl.getInstance().addScore(0,1,12);
ScoreServiceImpl.getInstance().addScore(0,0,10);
ScoreServiceImpl.getInstance().addScore(0,0,3);
树集通过分治法工作,它首先检查中间的人。 (这将是 1、4)并且由于 userIds 不匹配,因此不比较它们而是比较值。如果它比较了 userids,它会向左走,但它向右走,只比较 userid 为 one
的项目
您可以 always 比较两个值或 always 只比较 userId,但不能来回切换。
@Override
public int compareTo(UserHighScore uh) {
return Integer.compare(userId, uh.userId);
}
谁能找出这段代码中的并发错误?该代码对于一个线程来说工作得很好,但是一旦我同时启动 2 个线程并调用 addScore 方法,它就会向树 Map 添加重复项。
覆盖了compareTO的pojo如下:
public final class UserHighScore implements Comparable<UserHighScore>{
private final int userId;
private final int value;
public UserHighScore(int userId, int value) {
this.userId = userId;
this.value = value;
}
public int getUserId() {
return userId;
}
public int getValue() {
return value;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof UserHighScore)) {
return false;
}
UserHighScore userHighScore = (UserHighScore) obj;
return userHighScore.userId==userId;
}
@Override
public int compareTo(UserHighScore uh) {
if(uh.getUserId()==this.getUserId()) return 0;
if(uh.getValue()>this.getValue()) return 1;
return -1;
}
}
这是我用来模拟用户发出请求的代码:
class User implements Runnable
{
private ScoreServiceImpl scoreService=ScoreServiceImpl.getInstance();
CountDownLatch latch;
public User(CountDownLatch latch)
{
this.latch = latch;
}
@Override
public void run() {
for(int i=0;i<5;i++) {
scoreService.addScore(3,Integer.parseInt(Thread.currentThread().getName()),ThreadLocalRandom.current().nextInt(50000));
}
System.out.println(scoreService.getHighScoreList(3));
}
}
创建线程的主要方法是:
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(RestclientApplication.class, args);
CountDownLatch latch = new CountDownLatch(1);
User user1=new User(latch);
User user2=new User(latch);
Thread t1=new Thread(user1);
Thread t2=new Thread(user2);
t1.setName("1");
t2.setName("2");
t1.start();
t2.start();
//latch.countDown();
}
你的 compareTo 很古怪。你可以用这样的单线程获得相同的结果
ScoreServiceImpl.getInstance().addScore(0,1,4);
ScoreServiceImpl.getInstance().addScore(0,1,12);
ScoreServiceImpl.getInstance().addScore(0,0,10);
ScoreServiceImpl.getInstance().addScore(0,0,3);
树集通过分治法工作,它首先检查中间的人。 (这将是 1、4)并且由于 userIds 不匹配,因此不比较它们而是比较值。如果它比较了 userids,它会向左走,但它向右走,只比较 userid 为 one
的项目您可以 always 比较两个值或 always 只比较 userId,但不能来回切换。
@Override
public int compareTo(UserHighScore uh) {
return Integer.compare(userId, uh.userId);
}