2012-02-25 49 views
-1

我写了一段代码来实现自旋锁和互斥锁。
有一个有趣的,但。魔术师可以让我的程序保持活力。如果我删除了cout,我的程序将永远处于睡眠状态。 (这只发生在Linux中,Windows运行良好)
任何人都有线索?让我的程序保持活力的魔力cout

#include <pthread.h> 
#include <iostream> 
#include <queue> 
#include <sys/time.h> 
#include <stdexcept> 
#include <cstdio> 
#include <cstdlib> 
using namespace std; 

#define Tcount 10 
#define TheLock MutexLock 

static inline int TAS(volatile int * ptr) { 
    unsigned long result; 
    asm volatile("lock;" 
       "xchgl %0, %1;" 
       : "=r"(result), "=m"(*ptr) 
       : "0"(1), "m"(*ptr) 
       : "memory"); 
    return result; 
} 




class SpinLock { 
private: 
    int lock; 
    pthread_t owner; 
public: 

    SpinLock() { 
     lock = 0; 
    } 

    void getLock() { 
     while (TAS(&lock) == 1) { 

     } 

     owner = pthread_self(); 

    } 

    void releaseLock() { 
     if (lock == 0) { 
      cout << "Spin no lock" << endl; 
      return; 
     } else if (owner == pthread_self()) { 
      owner = NULL; 
      lock = 0; 
     } else { 
      throw runtime_error("Spin can't release"); 
     } 
    } 


}; 

class MutexLock { 
private: 
    int lock; 
    pthread_t owner; 
    queue<pthread_t> q; 
    SpinLock qLock; 
public: 

    MutexLock() { 
     lock = 0; 
    } 

    void getLock(int id) { 
     pthread_t self = pthread_self(); 
    cout<<"a"<<endl;// magic cout 

     if (TAS(&lock) == 0) { 
      owner = self; 
      return; 
     } 
     qLock.getLock(); 
     q.push(self); 
     qLock.releaseLock(); 

     while (owner != self) { 
     } 

    } 

    void releaseLock(int id) { 
     if (lock == 0) { 
      cout << "Mutex no lock" << endl; 
      return; 
     } else if (owner == pthread_self()) { 
      qLock.getLock(); 
      if (q.empty()) { 
       owner = NULL; 
       lock = 0; 
      } else { 
     owner = q.front(); 
       q.pop();   
      } 
      qLock.releaseLock(); 
     } else { 
       throw runtime_error("Mutex can't release"); 
     } 
    } 
}; 

TheLock lock; 
int g = 0; 
void* run(void* pt) { 

    int id = (int) pt; 
    for (int i = 0; i < 10000; i++) { 

     lock.getLock(id); 
     //cout<<"Thread "<<id<<" get lock, g="<<g<<endl; 
     int next = g + 1; 
     g = next; 
     //cout<<"Thread "<<id<<" release lock, g="<<g<<endl; 
     lock.releaseLock(id); 


    } 

    return NULL; 

} 

int main() { 

    pthread_t th[Tcount]; 

    long mtime, seconds, useconds; 
    struct timeval start, end; 
    gettimeofday(&start, NULL); 

    for (int i = 0; i < Tcount; i++) { 
     pthread_create(&th[i], NULL, run, (void*) (i+10)); 
    } 
    for (int i = 0; i < Tcount; i++) { 
     pthread_join(th[i], 0); 
    } 
    gettimeofday(&end, NULL); 

    seconds = end.tv_sec - start.tv_sec; 
    useconds = end.tv_usec - start.tv_usec; 

    mtime = ((seconds) * 1000000 + useconds); 

    cout << "g=" << g << endl; 
    cout << "time=" << mtime << endl; 



    return 0; 
} 
+0

尝试将其降低为最小代码示例,大约20行代码。 – 2012-02-25 21:12:38

+0

您可以制作一个展示此问题的最小示例吗? – bames53 2012-02-25 21:13:04

回答

2

您不能通过使用volatile关键字来实现互斥锁,因为操作可能不是原子操作。这意味着在操作完成之前,操作系统可能会切换到另一个线程。

对于互斥量,您必须使用操作系统。这是唯一知道线程何时被切换的东西。

+0

对不起,我不明白你的意思..... – user956159 2012-02-26 01:46:29

+2

Bascially你不能在C++(或任何其他语言)实现互斥体。它由操作系统给你。所以你上面的代码是没用的。 'volatile'关键字仅仅意味着编译器不会对其执行优化,因为它可能会彻底改变其他方法(例如时钟)而未被程序定义。 – 2012-02-26 05:06:21