互斥锁 / 什么是被锁定的互斥锁数据

mutex / what is the mutex data being locked?

本文关键字:数据 锁定 什么      更新时间:2023-10-16
#include <pthread.h>
#include <time.h>
#include "errors.h"

    typedef struct alarm_tag {
struct alarm_tag    *link;
int                 seconds;
time_t              time;   /* seconds from EPOCH */
char                message[64];
    } alarm_t;
    pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;
alarm_t *alarm_list = NULL;

void *alarm_thread (void *arg)
{
alarm_t *alarm;
int sleep_time;
time_t now;
int status;

while (1) {
    status = pthread_mutex_lock (&alarm_mutex);
    if (status != 0)
        err_abort (status, "Lock mutex");
    alarm = alarm_list;
    /*
     * If the alarm list is empty, wait for one second. This
     * allows the main thread to run, and read another
     * command. If the list is not empty, remove the first
     * item. Compute the number of seconds to wait -- if the
     * result is less than 0 (the time has passed), then set
     * the sleep_time to 0.
     */
    if (alarm == NULL)
        sleep_time = 1;
    else {
        alarm_list = alarm->link;
        now = time (NULL);
        if (alarm->time <= now)
            sleep_time = 0;
        else
            sleep_time = alarm->time - now;
#ifdef DEBUG
        printf ("[waiting: %d(%d)"%s"]n", alarm->time,
            sleep_time, alarm->message);
#endif
        }
    /*
     * Unlock the mutex before waiting, so that the main
     * thread can lock it to insert a new alarm request. If
     * the sleep_time is 0, then call sched_yield, giving
     * the main thread a chance to run if it has been
     * readied by user input, without delaying the message
     * if there's no input.
     */
    status = pthread_mutex_unlock (&alarm_mutex);
    if (status != 0)
        err_abort (status, "Unlock mutex");
    if (sleep_time > 0)
        sleep (sleep_time);
    else
        sched_yield ();
    /*
     * If a timer expired, print the message and free the
     * structure.
     */
    if (alarm != NULL) {
        printf ("(%d) %sn", alarm->seconds, alarm->message);
        free (alarm);
    }
}
}
int main (int argc, char *argv[])
{
        int status;
    char line[128];
    alarm_t *alarm, **last, *next;
    pthread_t thread;
status = pthread_create (
    &thread, NULL, alarm_thread, NULL);
if (status != 0)
    err_abort (status, "Create alarm thread");
while (1) {
    printf ("alarm> ");
    if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
    if (strlen (line) <= 1) continue;
    alarm = (alarm_t*)malloc (sizeof (alarm_t));
    if (alarm == NULL)
        errno_abort ("Allocate alarm");
    /*
     * Parse input line into seconds (%d) and a message
     * (%64[^n]), consisting of up to 64 characters
     * separated from the seconds by whitespace.
     */
    if (sscanf (line, "%d %64[^n]", 
        &alarm->seconds, alarm->message) < 2) {
        fprintf (stderr, "Bad commandn");
        free (alarm);
    } else {
        status = pthread_mutex_lock (&alarm_mutex);
        if (status != 0)
            err_abort (status, "Lock mutex");
        alarm->time = time (NULL) + alarm->seconds;
        /*
         * Insert the new alarm into the list of alarms,
         * sorted by expiration time.
         */
        last = &alarm_list;
        next = *last;
        while (next != NULL) {
            if (next->time >= alarm->time) {
                alarm->link = next;
                *last = alarm;
                break;
            }
            last = &next->link;
            next = next->link;
        }
        /*
         * If we reached the end of the list, insert the new
         * alarm there. ("next" is NULL, and "last" points
         * to the link field of the last item, or to the
         * list header).
         */
        if (next == NULL) {
            *last = alarm;
            alarm->link = NULL;
        }
#ifdef DEBUG
        printf ("[list: ");
        for (next = alarm_list; next != NULL; next = next->link)
            printf ("%d(%d)["%s"] ", next->time,
                next->time - time (NULL), next->message);
        printf ("]n");
#endif
        status = pthread_mutex_unlock (&alarm_mutex);
        if (status != 0)
            err_abort (status, "Unlock mutex");
    }
}
    }

嗨,这是我的代码,任何人都可以告诉我,因为互斥体没有在结构中声明。那么,当互斥锁锁定和解锁时,实际上正在更改哪些数据,有人可以启发我吗?

互斥锁保护的这组数据在哪里?

互斥对象是 alarm_mutex 。受其"保护"的数据不必在代码中明确提及;就像在中一样,不需要有语义连接。互斥锁是一种低级线程原语,因此用户需要围绕它构建自己的逻辑。在您的情况下,内存中的一个位置用于阻止代码的其他部分(访问实际数据的部分)进行干扰。

这样想:std::atomic<int> x;表示对其进行操作的原子性。 int x; mutex m;要求访问x的每一段代码都正确查看m以确保程序的正确性。这个低级的 acess 就是我们在您的示例中看到的。

pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;创建一个共享互斥对象,用于锁定/解锁。

pthread_mutex_lock会在互斥锁可用时立即锁定互斥锁。执行此行后,它对所有其他线程不可用。 pthread_mutex_unlock解锁互斥锁,使其再次可用于其他线程(解锁另一个线程的pthread_mutex_lock

互斥锁不知道它在保护什么。程序员的工作是知道这一点,并且只在互斥锁锁定时更改它正在保护的数据。

在这种特定情况下,似乎alarm列表是被锁定的数据。