See achieved from the bottom of the lock

For the following mutex.

Why lock?

Lock represents access to the critical region. Only with the operation of the lock objects to enter the critical region.

What is the nature of the lock?

Lock is essentially a data structure (or an object), the object retains the essential information needed to describe the lock. Such as whether the current lock is occupied, which is occupied by a thread. The lock of some of the tools, libraries, is actually a lock object information to make changes.

Locking operation => attempt to modify the lock object information, if the modification is successful, the program continues down, otherwise it will temporarily stay here. (Have stayed in two ways, one is the spin repeated attempts, the other is suspended to wait wake)

Unlocking operation => reset the lock object information.

Something like this (Note: this example is not accurate, will speak later)

typedef struct __lock_t {
    int flag;              //锁的状态 0-空闲, 1-被占用
} lock_t; 

void init(lock_t *mutex) { //初始化锁对象
    mutex->flag = 0;
}

void lock(lock_t *mutex) {
    while(mutex->flag == 1)
        ;// 自旋等待
    mutex->flag = 1;
}

void unlock(lock_t *mutex) {
    mutex->flag = 0;
}

Lock storage location information

See achieved from the bottom of the lock

One is retained in the process, because the operating system provides a virtual memory, so the lock object memory space, can only be accessed by the current process. And the thread of the same process can be shared memory resources. So, this lock object can only be accessed by the thread of the current process.

Another lock information is stored in other applications of the machine. For example the machine is not turned Redis external access. Such multiple applications of the machine can be managed by the schedule information in this Redis lock.

Another is to lock information stored in other machines (or the machine is turned Redis external accessible), so that other computer applications can also be accessed on the lock, which is distributed lock.

To modify the lock information

Problems

Mentioned earlier, there is a problem in front of the lock function to modify the operation of the lock information, we look at the problem in the end went wrong. Assume that our computer has only one CPU, this time there are two threads started trying to acquire a lock.

See achieved from the bottom of the lock

The result of this procedure is that when the thread B has been holding the lock, A thread can acquire the lock. We can not meet the "mutex" is defined, this code does not satisfy the correctness. So the problem is where is it? The problem is that these two operations is determined and modifications not atomic.

As in the example above, the thread A has just been executed is determined, not enough time to do the modification operation, a context switch occurs, the code execution thread B instead. A thread switch back when, in fact, a change condition has occurred.

Hardware support

The code for this problem is clearly not the applications can be resolved, because the OS context switch is determined, the general application of the right to interfere. But the hardware provides some instruction primitives that can help us solve this problem. These primitives have test-and-set, compare-and-swap, fetch-and-add, and so on, we can based on these primitives to implement a modified atomic operations lock information. For example, we can achieve based on test-and-set:

//test-and-set的C代码表示
int TestAndSet(int *ptr, int new) {
    int old = *ptr; //抓取旧值
    *ptr = new; //设置新值
    return old; //返回旧值
}

typedef struct __lock_t {
    int flag;
} lock_t;

void init (lock_t *lock) {
    lock->flag = 0;
}

void lock(lock_t *lock) {
    //如果为1,说明原来就有人在用
    //如果不为1,说明原来没人在用,同时设置1,表明锁现在归我使用了
    while (TestAndSet(&lock->flag, 1) == 1) 
        ; //spin-wait (do noting)
}

void unlock (lock_t *lock) {
    lock->flag = 0;
}

Why these instructions will not be interrupted by a context switch?

Context switch instruction is actually executed handover. A CPU executes an instruction is executed, test-and-set instruction is a CPU, for, so even if the need for a context switch, it will complete before executing the current instruction, and then performs a context switch instruction.

Guess you like

Origin blog.51cto.com/13904503/2416126