多线程 - java如何实现“自旋”(spin)
迷茫
迷茫 2017-04-17 11:41:22
[Java讨论组]

我本以为Thread.yield()是实现自旋的,不过yield()会放弃cpu时间片,那应该也会进行上下文切换吧?那就不是自旋了吧?(我理解的自旋是:当线程需要某个资源,但这个资源没有到位,这时就进行一个死循环,从而不放弃cpu执行时间,也不进行上下文切换)

那,我该怎么实现自旋呢?

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

全部回复(2)
ringa_lee

一个简单的while就可以满足你的要求。

目前的JVM实现自旋会消耗CPU,如果长时间不调用doNotify方法,doWait方法会一直自旋,CPU会消耗太大。

public class MyWaitNotify3{

  MonitorObject myMonitorObject = new MonitorObject();
  boolean wasSignalled = false;

  public void doWait(){
    synchronized(myMonitorObject){
      while(!wasSignalled){
        try{
          myMonitorObject.wait();
         } catch(InterruptedException e){...}
      }
      //clear signal and continue running.
      wasSignalled = false;
    }
  }

  public void doNotify(){
    synchronized(myMonitorObject){
      wasSignalled = true;
      myMonitorObject.notify();
    }
  }
}

请参考 这里, 假唤醒部分。

大家讲道理

个人觉得wait/notify是条件变量的一种,并不是操作系统意义上的自旋,自旋应该是一个空loop,当loop的条件被其他线程改变时再进入临界区,参考java锁的种类以及辨析(一):自旋锁,其中如果觉得空循环耗CPU,方法体里加上Thread.yield()。譬如以下是一个顺序打印ABC的程序:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CharacterPrint implements Runnable {

    private int state = 0;
    private final int COUNT = 10;

    private String[] chs = { "A", "B", "C", "D" };
    private final int N = chs.length;

    private Lock lock = new ReentrantLock();

    private CharacterPrint() {
    }

    @Override
    public void run() {
        for (int i = 0; i < N; i++) {
            createThread(i);
        }
    }

    private void createThread(final int i) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (state != i) {
                        Thread.yield();
                    }
                    ;
                    lock.lock();
                    for (int j = 0; j < COUNT; j++) {
                        System.out.println(chs[i]);
                    }
                    state = (i + 1) % N;
                } finally {
                    lock.unlock();
                }
            }
        }, "thread" + i).start();
    }

    public static void main(String[] args) {
        new CharacterPrint().run();
    }
}

最后想说,一直都不太清楚自旋锁和条件变量差在哪里,但在posix的规范里它们就是不同的东西,参考同步和互斥的POSXI支持(互斥锁,条件变量,自旋锁)

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号