30、深入理解计算机系统笔记,并发编程(concurrent)(2)-阿里云开发者社区

开发者社区> hopegrace> 正文

30、深入理解计算机系统笔记,并发编程(concurrent)(2)

简介: 1、共享变量 1)线程存储模型 线程由内核自动调度,每个线程都有它自己的线程上下文(thread context),包括一个惟一的整数线程ID(Thread ID,TID),栈,栈指针,程序计数器,通用目的寄存器和条件码。
+关注继续查看

1、共享变量

1)线程存储模型

线程由内核自动调度,每个线程都有它自己的线程上下文(thread context),包括一个惟一的整数线程IDThread ID,TID),栈,栈指针,程序计数器,通用目的寄存器和条件码。每个线程和其他线程一起共享进程上下文的剩余部分,包括整个用户的虚拟地址空间,它是由只读文本(代码),读/写数据,堆以及所有的共享库代码和数据区域组成的,还有,线程也共享同样的打开文件的集合。[1]

寄存器从不共享,而虚拟存储器总是共享。

The memory model for the separate thread stacks is not as clean(整齐清楚的). These stacks are contained in the stack area of the virtual address space, and are usually accessed independently by their respective threads. We say usually rather than always, because different thread stacks are not protected from other threads. So if a thread somehow manages to acquire a pointer to another threads stack, then it can read and write any part of that stack. 示例29行中, where the peer threads reference the contents of the main threads stack indirectly through the global ptr variable.

2)将变量映射到存储器

    和全局变量一样,虚拟存储器的/写区域只包含在程序中声明的每个本地静态变量的一个实例。每个线程的栈都包含它自己的所有本地自动变量的实例。

3)我们说变量v是共享的,当且仅当它的一个实例被一个以上的线程引用。

示例代码

/* $begin sharing */
#include "csapp.h"
#define N 2
void *thread(void *vargp);

char **ptr;  /* global variable */

int main() 
{
    int i;  
    pthread_t tid;
    char *msgs[N] = {
	"Hello from foo",  
	"Hello from bar"   
    };

    ptr = msgs; 
    for (i = 0; i < N; i++)  
        Pthread_create(&tid, NULL, thread, (void *)i); 
    Pthread_exit(NULL); 
}

void *thread(void *vargp) 
{
    int myid = (int)vargp; //cnt是共享的,而myid不是共享的
    static int cnt = 0;
    printf("[%d]: %s (cnt=%d)\n", myid, ptr[myid], ++cnt);
}
/* $end sharing */

2、用信号量同步

当对同一共享变量,有多个线程进行更新时,由于每一次更新,对该变量来说,都有“加载到寄存器,更新之,存储写回到存储器”这个过程,多个线程操作时,便会产生错位,混乱的情况,有必要对共享变量作一保护,使这个更新操作具有原子性。

信号量s是具有非页整数值的全局变量,只能由两种特殊的操作来处理,称为PV操作。

P(s):

  while (s <= 0); s--;

     V (s): s++;

    The P operation waits for the semaphore s to become nonzero, and then decrements it.The V operation increments s.

1)基本思想是,将每个共享变量(或者相关共享变量集合)与一个信号量s(初始值1)联系起来,然后用P(s),V(s)操作将相应的临界区(一段代码)包围起来。以这种方法来保护共享变量的信号量叫做二进制信号量(binary semaphore),因为值总是10

The definitions of P and V ensure that a running program can never enter a state where a properly initialized semaphore has a negative value.

11.4.4有posix信号量的简介。

2)二进制信号量通常叫做互斥锁,在互斥锁上执行一个P操作叫做加锁,V操作叫做解锁;一个已经对一个互斥锁加锁而还没有解锁的线程被称为占用互斥锁。

3、用信号量来调度共享资源

这种情况下,一个线程用信号量来通知另一个线程,程序状态中的某个条件已经为真了。如生产者-消费者问题。

示例代码

#ifndef __SBUF_H__
#define __SBUF_H__

#include "csapp.h"

/* $begin sbuft */
typedef struct {
    int *buf;          /* Buffer array */         
    int n;             /* Maximum number of slots */
    int front;         /* buf[(front+1)%n] is first item */
    int rear;          /* buf[rear%n] is last item */
    sem_t mutex;       /* Protects accesses to buf */
    sem_t slots;       /* Counts available slots */
    sem_t items;       /* Counts available items */
} sbuf_t;
/* $end sbuft */

void sbuf_init(sbuf_t *sp, int n);
void sbuf_deinit(sbuf_t *sp);
void sbuf_insert(sbuf_t *sp, int item);
int sbuf_remove(sbuf_t *sp);

#endif /* __SBUF_H__ */
//source code
/* $begin sbufc */
#include "csapp.h"
#include "sbuf.h"

/* Create an empty, bounded, shared FIFO buffer with n slots */
/* $begin sbuf_init */
void sbuf_init(sbuf_t *sp, int n)
{
    sp->buf = Calloc(n, sizeof(int)); 
    sp->n = n;                       /* Buffer holds max of n items */
    sp->front = sp->rear = 0;        /* Empty buffer iff front == rear */
    Sem_init(&sp->mutex, 0, 1);      /* Binary semaphore for locking */
    Sem_init(&sp->slots, 0, n);      /* Initially, buf has n empty slots */
    Sem_init(&sp->items, 0, 0);      /* Initially, buf has zero data items */
}
/* $end sbuf_init */

/* Clean up buffer sp */
/* $begin sbuf_deinit */
void sbuf_deinit(sbuf_t *sp)
{
    Free(sp->buf);
}
/* $end sbuf_deinit */

/* Insert item onto the rear of shared buffer sp */
/* $begin sbuf_insert */
void sbuf_insert(sbuf_t *sp, int item)
{
    P(&sp->slots);                          /* Wait for available slot */
    P(&sp->mutex);                          /* Lock the buffer */
    sp->buf[(++sp->rear)%(sp->n)] = item;   /* Insert the item */
    V(&sp->mutex);                          /* Unlock the buffer */
    V(&sp->items);                          /* Announce available item */
}
/* $end sbuf_insert */

/* Remove and return the first item from buffer sp */
/* $begin sbuf_remove */
int sbuf_remove(sbuf_t *sp)
{
    int item;
    P(&sp->items);                          /* Wait for available item */
    P(&sp->mutex);                          /* Lock the buffer */
    item = sp->buf[(++sp->front)%(sp->n)];  /* Remove the item */
    V(&sp->mutex);                          /* Unlock the buffer */
    V(&sp->slots);                          /* Announce available slot */
    return item;
}
/* $end sbuf_remove */
/* $end sbufc */

参考

[1] http://www.cnblogs.com/mydomain/archive/2011/07/10/2102147.html

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
JAVA多线程高并发学习笔记(三)——Callable、Future和FutureTask
为什么要是用Callable和Future Runnable的局限性 Executor采用Runnable作为基本的表达形式,虽然Runnable的run方法能够写入日志,写入文件,写入数据库等操作,但是它不能返回一个值,或者抛出一个受检查的异常,有些需要返回值的需求就不能满足了。
1342 0
Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock。 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍ReentrantLock。
1073 0
Java多线程高并发学习笔记——阻塞队列
在探讨可重入锁之后,接下来学习阻塞队列,这篇文章也是断断续续的写了很久,因为最近开始学ssm框架,准备做一个自己的小网站,后续可能更新自己写网站的技术分享。 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/superfj/p/7757876.html 阻塞队列是什么? 首先了解队列,队列是数据先进先出的一种数据结构。
953 0
Spring Security笔记:Hello World
本文演示了Spring Security的最最基本用法,二个页面(或理解成二个url),一个需要登录认证后才能访问(比如:../admin/),一个可匿名访问(比如:../welcome) 注:以下内容参考了 http://www.
832 0
【高并发】又一个朋友面试栽在了Thread类的stop()方法和interrupt()方法上!
新一轮的面试已经过去,可能是疫情的原因吧,很多童鞋纷纷留言说今年的面试题难度又提高了,尤其是对并发编程的知识。我细想了下,也许有那么点疫情的原因吧,但无论面试的套路怎么变,只要掌握了核心知识和底层原理,吊打面试官应该不难吧。玩笑归玩笑,学习知识并不只是为了应付面试,更应该将这些知识运用到实际的工作中。
22 0
【转】自动实时监控Windows2003服务器终端登录并发邮件和发短信通知
记得以前管理的一批windows服务器,一些开源程序做的web站点总会遭到入侵。然而就想找找看有没有办法可以知道服务器有没有被入侵。服务器在什么时候登陆过,如果登陆马上发邮件通知,感觉这种问题肯定有人处理过,于是网上搜罗了一下。
1117 0
《逻辑与计算机设计基础(原书第5版)》——1.2 计算机系统设计的抽象层次
本节书摘来自华章计算机《逻辑与计算机设计基础(原书第5版)》一书中的第1章,第1.2节,作者:(美)M.莫里斯·马诺(M. Morris Mano)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1717 0
《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一1.2 团队建设
本节书摘来华章计算机《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一书中的第1章 ,第1.2节,陈以农 陈文智 韩德强 著 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
831 0
+关注
698
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载