保持我的程序活着的神奇cout

时间:2012-02-25 21:05:22

标签: c++ linux locking

我写了一个代码来实现自旋锁和互斥锁 有一个有趣的但是。一个神奇的cout可以保持我的程序活着。如果我删除了cout,我的程序将永远在睡觉。 (这只发生在Linux上.Windows正常运行)
任何人都有线索?

#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;
}

1 个答案:

答案 0 :(得分:2)

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

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