We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
在getIdFromSegmentBuffer 方法中, 假设 当前Segment已经没有可用id了,当前线程A 启动线程B 准备NextSegment。 假设此时已经有100个线程阻塞在取号的方,具体也就是waitAndSleep 方法的地方。 当线程B准备就绪NextSegment后, 线程C及时发现SegmentBuffer准备就绪并先获取到了cpu,这个时候线程C会执行Segment的切换工作。切换之后将SegmentBuffer的nextReady设置为false。 对于线程A和其他被阻塞的线程而言,当这些线程 从waitAndSleep方法返回 后 需要 依次获取写锁,然后从当前Segment中取号。显然这些线程没必要依次获取写锁,而且获取SegmentBuffer写锁 会影响 另外的其他尚未被阻塞线程并发使用读锁从当前Segment中获取id。这是第一种情况。
第二种情况就是,假设线程B 准备nextSegment失败了,此时已经有了100个线程处于阻塞状态waitAndSleep,那么这100个线程会依次获取写锁并检查发现SegmentBuffer的nextReady为false,然后返回 取号失败的结果 这些线程就退出了,因此触发nextSegment的准备工作需要 等待下一次取号请求。
按照我的理解:对于唤醒后的线程,如果SegmentBuffer的nextReady为false 则当前线程 没必要通过获取读锁来取号。 只需要走正常的取号流程就可以了。这个时候对于第二种情况也会有改善,因为走了正常的取号流程 也就相当于会启动新的线程执行nextSegment的初始化工作,而不是直接返回取号失败结果。
public Result getIdFromSegmentBuffer(final SegmentBuffer buffer) { while (true) { buffer.rLock().lock(); try { final Segment segment = buffer.getCurrent(); if (!buffer.isNextReady() && (segment.getIdle() < 0.9 * segment.getStep()) && buffer.getThreadRunning().compareAndSet(false, true)) { service.execute(new Runnable() { @Override public void run() { Segment next = buffer.getSegments()[buffer.nextPos()]; boolean updateOk = false; try { updateSegmentFromDb(buffer.getKey(), next); updateOk = true; logger.info("update segment {} from db {}", buffer.getKey(), next); } catch (Exception e) { logger.warn(buffer.getKey() + " updateSegmentFromDb exception", e); } finally { if (updateOk) { buffer.wLock().lock(); buffer.setNextReady(true); buffer.getThreadRunning().set(false); buffer.wLock().unlock(); } else { buffer.getThreadRunning().set(false); } } } }); } long value = segment.getValue().getAndIncrement(); if (value < segment.getMax()) { return new Result(value, Status.SUCCESS); } } finally { buffer.rLock().unlock(); } waitAndSleep(buffer); //这个地方优化 buffer.wLock().lock(); try { final Segment segment = buffer.getCurrent(); long value = segment.getValue().getAndIncrement(); if (value < segment.getMax()) { return new Result(value, Status.SUCCESS); } if (buffer.isNextReady()) { buffer.switchPos(); buffer.setNextReady(false); } else { //这个地方优化 logger.error("Both two segments in {} are not ready!", buffer); return new Result(EXCEPTION_ID_TWO_SEGMENTS_ARE_NULL, Status.EXCEPTION); } } finally { buffer.wLock().unlock(); } } }
@thelight1 @Yaccc ##191
The text was updated successfully, but these errors were encountered:
(只需要走正常的取号流程就可以了。这个时候对于第二种情况也会有改善)您指的是在调用一次getIdFromSegmentBuffer方法吗
Sorry, something went wrong.
No branches or pull requests
在getIdFromSegmentBuffer 方法中, 假设 当前Segment已经没有可用id了,当前线程A 启动线程B 准备NextSegment。 假设此时已经有100个线程阻塞在取号的方,具体也就是waitAndSleep 方法的地方。 当线程B准备就绪NextSegment后, 线程C及时发现SegmentBuffer准备就绪并先获取到了cpu,这个时候线程C会执行Segment的切换工作。切换之后将SegmentBuffer的nextReady设置为false。 对于线程A和其他被阻塞的线程而言,当这些线程 从waitAndSleep方法返回 后 需要 依次获取写锁,然后从当前Segment中取号。显然这些线程没必要依次获取写锁,而且获取SegmentBuffer写锁 会影响 另外的其他尚未被阻塞线程并发使用读锁从当前Segment中获取id。这是第一种情况。
第二种情况就是,假设线程B 准备nextSegment失败了,此时已经有了100个线程处于阻塞状态waitAndSleep,那么这100个线程会依次获取写锁并检查发现SegmentBuffer的nextReady为false,然后返回
取号失败的结果 这些线程就退出了,因此触发nextSegment的准备工作需要 等待下一次取号请求。
按照我的理解:对于唤醒后的线程,如果SegmentBuffer的nextReady为false 则当前线程 没必要通过获取读锁来取号。 只需要走正常的取号流程就可以了。这个时候对于第二种情况也会有改善,因为走了正常的取号流程 也就相当于会启动新的线程执行nextSegment的初始化工作,而不是直接返回取号失败结果。
@thelight1 @Yaccc
##191
The text was updated successfully, but these errors were encountered: