Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

volatile多线程并不安全 #15

Open
fsan42 opened this issue Nov 21, 2022 · 2 comments
Open

volatile多线程并不安全 #15

fsan42 opened this issue Nov 21, 2022 · 2 comments

Comments

@fsan42
Copy link

fsan42 commented Nov 21, 2022

if (N > commitIndex) {
    LogEntry entry = logModule.read(N);
    if (entry != null && entry.getTerm() == currentTerm) {
        commitIndex = N;
    }
}

//  响应客户端(成功一半)
if (success.get() >= (count / 2)) {
    // 更新
    commitIndex = logEntry.getIndex();
    //  应用到状态机
    getStateMachine().apply(logEntry);
    lastApplied = commitIndex;

    log.info("success apply local state machine,  logEntry info : {}", logEntry);
    // 返回成功.
    return ClientKVAck.ok();
} else {
    // 回滚已经提交的日志.
    logModule.removeOnStartIndex(logEntry.getIndex());
    log.warn("fail apply local state  machine,  logEntry info : {}", logEntry);
    // TODO 不应用到状态机,但已经记录到日志中.由定时任务从重试队列取出,然后重复尝试,当达到条件时,应用到状态机.
    // 这里应该返回错误, 因为没有成功复制过半机器.
    return ClientKVAck.fail();
}

这种涉及到多线程操作的变量比如commitIndex 虽然是 volatile修饰了 但是是不是仍然存在线程安全问题可能被一个旧的更小的值覆盖掉?而这里的赋值有很多先查询后写入的过程,那如果这里有问题,我们继续推断一下,是不是所有多线程操作的变量都有可能出现更新丢失?

@Kakk22
Copy link

Kakk22 commented Feb 5, 2023

方法级别加了synchronized

@kebukeYi
Copy link

if (N > commitIndex) {
    LogEntry entry = logModule.read(N);
    if (entry != null && entry.getTerm() == currentTerm) {
        commitIndex = N;
    }
}

//  响应客户端(成功一半)
if (success.get() >= (count / 2)) {
    // 更新
    commitIndex = logEntry.getIndex();
    //  应用到状态机
    getStateMachine().apply(logEntry);
    lastApplied = commitIndex;

    log.info("success apply local state machine,  logEntry info : {}", logEntry);
    // 返回成功.
    return ClientKVAck.ok();
} else {
    // 回滚已经提交的日志.
    logModule.removeOnStartIndex(logEntry.getIndex());
    log.warn("fail apply local state  machine,  logEntry info : {}", logEntry);
    // TODO 不应用到状态机,但已经记录到日志中.由定时任务从重试队列取出,然后重复尝试,当达到条件时,应用到状态机.
    // 这里应该返回错误, 因为没有成功复制过半机器.
    return ClientKVAck.fail();
}

这种涉及到多线程操作的变量比如commitIndex 虽然是 volatile修饰了 但是是不是仍然存在线程安全问题可能被一个旧的更小的值覆盖掉?而这里的赋值有很多先查询后写入的过程,那如果这里有问题,我们继续推断一下,是不是所有多线程操作的变量都有可能出现更新丢失?

你最好将这块代码所在的 类#方法 说明白啊;
DefaultNode#handlerClientRequest() 方法

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants