GCD之信号量机制二

在前面GCD之信号量机制一中介绍了通过信号量设置并行最大线程数,依此信号量还可以防止多线程访问公有变量时数据有误,下面的代码能说明。

1.下面是不采用信号量修改公有变量的值


dispatch_group_t group=dispatch_group_create();

//    dispatch_semaphore_t semaphore=dispatch_semaphore_create(1);

    dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    __block int count=1000;

    for (int i=0; i<100; i++) {

        //信号量减1,如果同时开启10个以上的线程,则信号量小于等于0,此时就会阻塞该线程。

//        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        dispatch_group_async(group, queue, ^{

            int value = (arc4random() % 4) + 6;

            NSLog(@"%d-%d= %d",count,value,count-value);

            count=count-value;

        //每个线程执行减1后通过信号量通知加1,这样始终保持线程在10个之内

//        dispatch_semaphore_signal(semaphore);

        });

    }

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

 2.运行结果如下:

3.声明一个初始值为1的信号量来开启线程修改公有变量时


dispatch_group_t group=dispatch_group_create();

   dispatch_semaphore_t semaphore=dispatch_semaphore_create(1);

   dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

   __block int count=1000;

   for (int i=0; i<100; i++) {

       //信号量减1,如果同时开启10个以上的线程,则信号量小于等于0,此时就会阻塞该线程。

       dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

       dispatch_group_async(group, queue, ^{

           int value = (arc4random() % 4) + 6;

           NSLog(@"%d-%d= %d",count,value,count-value);

           count=count-value;

       //每个线程执行减1后通过信号量通知加1,这样始终保持线程在10个之内

       dispatch_semaphore_signal(semaphore);

       });

   }

   dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

 4.运行结果如下:

可以看到,第一代码段时修改公有变量时不是有序的,第二个代码段才是真正正确的修改顺序。这过程可取款的过程一样,金额是1000,可能在不同的地方同时取款,取款时不可能金额是像第一代码段那样。这个和C#的lock关键字有一样的效果。

时间: 2024-11-10 01:01:42

GCD之信号量机制二的相关文章

GCD之信号量机制一

在使用NSOperationQueue进行多线程编程时,可通过[queue setMaxConcurrentOperationCount:5]来设置线程池中最多并行的线程数,在GCD中信号量机制也和它相似,可以控制并发的线程数量. 1.首先熟悉下几个函数 dispatch_semaphore_create 创建一个信号量,设置一个初始值 dispatch_semaphore_signal 发送一个信号,信号通知,信号量+1 dispatch_semaphore_wait 等待信号,信号量-1 当

深入SQL SERVER 2000的内存管理机制(二)

server 深入SQL SERVER 2000的内存管理机制(二)     http://msdn.microsoft.com/data/default.aspx?pull=/library/en-us/dnsqldev/html/sqldev_01262004.asp   可访问大地址的应用 (Large-Address-Aware Executables) 在Windows增加支持/3GB参数以前,一个应用程序是无法访问一个带有高位设置的指针.一个32位的指针只有前31位地址空间可以被用户

GCD深入理解(二)

转自@nixzhu的GitHub主页(译者:Riven.@nixzhu),原文<Grand Central Dispatch In-Depth: Part 2/2>   欢迎来到GCD深入理解系列教程的第二部分(也是最后一部分).   在本系列的第一部分中,你已经学到超过你想像的关于并发.线程以及GCD 如何工作的知识.通过在初始化时利用 dispatch_once,你创建了一个线程安全的 PhotoManager 单例,而且你通过使用 dispatch_barrier_async 和 dis

java的线程机制(二) Thread的生命周期

之前讲到Thread的创建,那是Thread生命周期的第一步,其后就是通过start()方法来启动Thread,它会 执行一些内部的管理工作然后调用Thread的run()方法,此时该Thread就是alive(活跃)的,而且我们还可以通 过isAlive()方法来确定该线程是否启动还是终结. 一旦启动Thread后,我们就只能执行一个方 法:run(),而run()方法就是负责执行Thread的任务,所以终结Thread的方法很简单,就是终结run()方法.仔 细查看文档,我们会发现里面有一个

linux网络编程之System V 信号量(二)

用信号量实现进程互斥示例和解决哲学家就餐问题 一.我们在前面讲进程间通信的时候提到过进程互斥的概念,下面写个程序来模拟一下,程序流程如下图: 即父进程打印字 符O,子进程打印字符X,每次打印一个字符后要sleep 一下,这里要演示的效果是,在打印程序的边界有PV操作,故每个进 程中间sleep 的时间即使时间片轮转到另一进程,由于资源不可用也不会穿插输出其他字符,也就是说O或者X字符都会是成 对出现的,如OOXXOOOOXXXXXXOO.... 程序如下: #include<sys/types.

Android事件传递机制(二)deprecated

main.xml如下: <!-- 自定义布局中,放置一个自定义控件 --> <cn.c.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <cn.c.MyLinearLayout

深入浅出之Smarty模板引擎工作机制(二)

源代码下载地址:深入浅出之Smarty模板引擎工作机制 接下来根据以下的Smarty模板引擎原理流程图开发一个自己的模板引擎用于学习,以便加深理解.   Smarty模板引擎的原理,其实是这么一个过程: 把模板文件编译成php文件,然后每次都去读取下模板的修改时间,没有修改就不编译.然后include这个"编译"后的PHP文件. 所谓编译也就是模板用正则替换成含PHP代码的过程. 实际上并不会每次请求都编译,所以性能尚可.  模板文件和php程序文件经过模板引擎的编译后合成为一个文件,

php Smarty模板引擎工作机制(二)

所谓编译也就是模板用正则替换成含PHP代码的过程. 实际上并不会每次请求都编译,所以性能尚可. 模板文件和php程序文件经过模板引擎的编译后合成为一个文件,即编译后的文件. 接下来,我们根据该原理流程写一个简单的模板引擎...... 先贴上核心代码: Smarty.class.php文件  代码如下 复制代码 <?php     class Smarty{         public $template_dir;//模板目录         public $compile_dir;//编译目录

Spring中ApplicationContext的事件机制(二 内定事件)

在Spring中已经定义了五个标准事件,分别介绍如下: 1)ContextRefreshedEvent:当ApplicationContext初始化或者刷新时触发该事件. 2)ContextClosedEvent:当ApplicationContext被关闭时触发该事件.容器被关闭时,其管理的所有 单例Bean都被销毁. 3)RequestHandleEvent:在Web应用中,当一个http请求(request)结束触发该事件. ContestStartedEvent:Spring2.5新增的