代码之家  ›  专栏  ›  技术社区  ›  dsimcha

高效的独立同步块?

  •  5
  • dsimcha  · 技术社区  · 14 年前

    synchronized updateStructure1();
    synchronized updateStructure2();
    // ...
    

    这看起来效率很低,因为如果多个线程尝试更新结构1,但没有线程尝试更新结构2,那么它们都会阻塞等待保护结构1的锁,而结构2的锁则处于未锁定状态。

    这是一个与语言无关的问题,但如果有帮助的话,我使用的语言是D。

    6 回复  |  直到 14 年前
        1
  •  1
  •   JSBÕ±Õ¸Õ£Õ¹    14 年前

    我不知道有没有标准的方法。但是,我将实现以下内容:

    do
    {
        if (!updatedA && mutexA.tryLock())
        {
            scope(exit) mutexA.unlock();
            updateA();
            updatedA = true;
        }
    
        if (!updatedB && mutexB.tryLock())
        {
            scope(exit) mutexB.unlock();
            updateB();
            updatedB = true;
        }
    }
    while (!(updatedA && updatedB));
    

    一些聪明的元编程可能会减少重复,但我把它作为一个练习留给你。

        2
  •  2
  •   Karmastan    14 年前

    Actors ,您可以始终让更新线程生成一个新线程来更改每个对象,其中每个线程只是锁定、修改和解锁每个对象。然后让更新线程在返回之前连接到它的所有子线程。这会将问题推到运行时的时间表上,并且可以任意安排这些子线程以获得最佳性能。

    您可以在具有较重线程的langauges中执行此操作,但是spawn和join可能会有太多开销(尽管线程池可能会减轻一些开销)。

        3
  •  1
  •   David G    12 年前

    抱歉,如果我太天真了,你不只是在对象上同步以使关注点独立吗?

    例如

    public Object lock1 = new Object; // access to resource 1 
    public Object lock2 = new Object; // access to resource 2
    
    updateStructure1() {
       synchronized( lock1 ) {
          ...
       }
    }
    
    updateStructure2() {
       synchronized( lock2 ) {
         ...
       }
    }
    
        4
  •  0
  •   Karmastan    14 年前

    据我所知,没有一个标准的方法来实现这一点,你必须弄脏你的手。

    work = unshared list of objects that need updating
    while work is not empty:
        found = false
        for each obj in work:
            try locking obj
            if successful:
                remove obj from work
                found = true
                obj.update()
                unlock obj
        if !found:
            // Everything is locked, so we have to wait
            obj = randomly pick an object from work
            remove obj from work
            lock obj
            obj.update()
            unlock obj
    

    更新线程只有在发现 全部的

    另外,可以想象,当更新程序处于 循环,因此更新程序将跳过它。但是,如果您所做的工作量足够大,相对于遍历该循环的成本而言,错误冲突应该很少发生,而且只有在争用率极高的情况下才会发生。

        5
  •  0
  •   0scar    14 年前

    对不起,我不知道什么“标准”的方法。下面这是一个线程组,由 Swarm -类,它对作业列表进行黑客攻击,直到所有任务都完成为止,采用循环方式,并确保使用尽可能多的线程。我不知道没有工作清单怎么办。

    免责声明:我对D和并发编程非常陌生,所以代码相当业余。我认为这更像是一个有趣的练习(我也明白这不是你想要的。如果有人有什么建议,我很想听!

    import  core.thread,
            core.sync.mutex,
            std.c.stdio,
            std.stdio;
    
    class Swarm{
        ThreadGroup group;
        Mutex mutex;
        auto numThreads = 1;
        void delegate ()[int] jobs;
        this(void delegate()[int] aJobs, int aNumThreads){
            jobs = aJobs;
            numThreads = aNumThreads;
            group = new ThreadGroup;
            mutex = new Mutex();
        }
        void runBlocking(){
            run();
            group.joinAll();
        }
        void run(){
            foreach(c;0..numThreads)
                group.create( &swarmJobs );
        }
        void swarmJobs(){
            void delegate () myJob;
            do{
                myJob = null;
                synchronized(mutex){
                    if(jobs.length > 0)
                        foreach(i,job;jobs){
                            myJob = job;
                            jobs.remove(i);
                            break;
                        }
                }
                if(myJob)
                    myJob();
            }while(myJob)
        }
    }
    class Jobs{
        void job1(){
            foreach(c;0..1000){
                foreach(j;0..2_000_000){}
                writef("1");
                fflush(core.stdc.stdio.stdout);
            }
        }
        void job2(){
            foreach(c;0..1000){
                foreach(j;0..1_000_000){}
                writef("2");
                fflush(core.stdc.stdio.stdout);
            }
        }
    }
    void main(){
        auto jobs = new Jobs();
        void delegate ()[int] jobsList = 
             [1:&jobs.job1,2:&jobs.job2,3:&jobs.job1,4:&jobs.job2];
        int numThreads = 2;
        auto swarm = new Swarm(jobsList,numThreads);
        swarm.runBlocking();
        writefln("end");
    }
    
        6
  •  0
  •   Conrad Frix    14 年前

    没有标准溶液,而是根据你的需要而定的一类标准溶液。

    http://en.wikipedia.org/wiki/Scheduling_algorithm