Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 信号量&;线程-重点是什么?_Multithreading_Semaphore - Fatal编程技术网

Multithreading 信号量&;线程-重点是什么?

Multithreading 信号量&;线程-重点是什么?,multithreading,semaphore,Multithreading,Semaphore,我一直在阅读关于信号量的文章,偶然发现了这篇文章: 因此,本页指出,如果有两个线程访问相同的数据,事情可能会变得糟糕。解决方案是只允许一个线程同时访问数据 这很清楚,我理解解决方案,只是为什么有人需要线程来做这件事?重点是什么?如果线程被阻塞,只有一个线程可以执行,为什么还要使用它们呢?没有优势。(或者这只是一个愚蠢的例子;在这种情况下,请给我指出一个合理的例子) 提前感谢。当您使用多线程时,并非所有运行的代码都会被阻塞。例如,如果您有一个队列,并且有两个线程正在从该队列中读取数据,那么您将确

我一直在阅读关于信号量的文章,偶然发现了这篇文章:

因此,本页指出,如果有两个线程访问相同的数据,事情可能会变得糟糕。解决方案是只允许一个线程同时访问数据

这很清楚,我理解解决方案,只是为什么有人需要线程来做这件事?重点是什么?如果线程被阻塞,只有一个线程可以执行,为什么还要使用它们呢?没有优势。(或者这只是一个愚蠢的例子;在这种情况下,请给我指出一个合理的例子)


提前感谢。

当您使用多线程时,并非所有运行的代码都会被阻塞。例如,如果您有一个队列,并且有两个线程正在从该队列中读取数据,那么您将确保没有线程同时从该队列中读取数据,因此该部分将被阻塞,但这可能是占用较少时间的部分。一旦从队列中检索到要处理的项,所有其余的代码都可以异步运行。

使用多线程时,并非所有运行的代码都会被阻塞。例如,如果您有一个队列,并且有两个线程正在从该队列中读取数据,那么您将确保没有线程同时从该队列中读取数据,因此该部分将被阻塞,但这可能是占用较少时间的部分。一旦从队列中检索到要处理的项,所有其余的代码都可以异步运行。

这当然是一个SSCCE(简短、自包含、正确的示例) 假设您有两个工作线程,它们执行大量工作并将结果写入文件。 您只需锁定文件(共享资源)访问。

这当然是一个SSCCE(简短、自包含、正确的示例) 假设您有两个工作线程,它们执行大量工作并将结果写入文件。 您只需锁定文件(共享资源)访问权限。

请考虑以下事项:

void update_shared_variable() {
    sem_wait( &g_shared_variable_mutex );

    g_shared_variable++;

    sem_post( &g_shared_variable_mutex );
}

void thread1() {

    do_thing_1a();
    do_thing_1b();
    do_thing_1c();

    update_shared_variable();   // may block
}

void thread2() {

    do_thing_2a();
    do_thing_2b();
    do_thing_2c();

    update_shared_variable();   // may block
}
请注意,所有的
do\u thing\u xx
功能仍然同时发生。只有当线程需要修改某些共享(全局)状态或使用某些共享资源时,信号量才会起作用。因此,只有当另一个线程试图同时访问共享对象时,该线程才会阻塞

现在,如果您的线程所做的唯一一件事是使用一个共享变量/资源,那么您是正确的-拥有线程没有任何意义(由于上下文切换,它实际上比一个线程的效率低)。

考虑以下几点:

void update_shared_variable() {
    sem_wait( &g_shared_variable_mutex );

    g_shared_variable++;

    sem_post( &g_shared_variable_mutex );
}

void thread1() {

    do_thing_1a();
    do_thing_1b();
    do_thing_1c();

    update_shared_variable();   // may block
}

void thread2() {

    do_thing_2a();
    do_thing_2b();
    do_thing_2c();

    update_shared_variable();   // may block
}
请注意,所有的
do\u thing\u xx
功能仍然同时发生。只有当线程需要修改某些共享(全局)状态或使用某些共享资源时,信号量才会起作用。因此,只有当另一个线程试图同时访问共享对象时,该线程才会阻塞


现在,如果您的线程所做的唯一一件事是使用一个共享变量/资源,那么您是正确的-拥有线程没有任何意义(由于上下文切换,它实际上比只有一个线程效率低)。

线程背后的思想是允许同时处理。必须对共享资源进行管理,以避免死锁或饥饿等情况。如果某个过程可能需要一段时间,那么为什么不创建这些过程的多个实例以使它们更快地完成呢?瓶颈正是您提到的,当进程必须等待I/O时


与处理时间相比,等待共享资源时被阻塞的时间很短,此时您需要使用多个线程。

线程背后的思想是允许同时处理。必须对共享资源进行管理,以避免死锁或饥饿等情况。如果某个过程可能需要一段时间,那么为什么不创建这些过程的多个实例以使它们更快地完成呢?瓶颈正是您提到的,当进程必须等待I/O时


与处理时间相比,在等待共享资源时被阻塞的时间很短,此时您需要使用多个线程。

简单示例的问题

如果您试图解决的问题可以分解为可以并行执行的部分,那么线程是一件好事

一个稍微不那么简单的例子——想象一个for循环,其中每次迭代中处理的数据每次都不同。在这种情况下,您可以在单独的线程中同时执行for循环的每个迭代。事实上,像英特尔这样的编译器会自动将适合循环的线程转换为适合您的线程。在这种特殊情况下,由于迭代的数据独立性,不需要信号量

但是假设您想要处理一个数据流,并且处理有两个不同的步骤,a和B。无线程方法将涉及读取一些数据,然后执行a,然后执行B,然后在读取更多输入之前输出数据。或者,您可以让一个线程读取并执行a,另一个线程执行B并输出。那么,如何获得从第一个线程到第二个线程的中间结果呢

一种方法是使用内存缓冲区来包含临时结果。第一个线程可以将临时结果写入内存缓冲区,第二个线程可以从中读取。但是由于两个线程独立运行,第一个线程无法知道覆盖该缓冲区是否安全,第二个线程也无法知道何时读取该缓冲区

在这里,您可以使用信号量来同步两个线程的操作。第一个线程接收一个我将称为空的信号量,填充缓冲区,然后发布一个名为filled的信号量。同时,第二个线程将获取已填充的信号量,读取缓冲区,然后将post清空。只要filled初始化为0,empty初始化为1,它就可以工作。第二