当前位置: 首页 > wzjs >正文

河北专业网站建设seo的排名机制

河北专业网站建设,seo的排名机制,注册公司需要的网站建设,网站流量导入是什么意思一、什么是信号量? 信号量(Semaphore)是一种用于同步和互斥的机制,主要用于控制对共享资源的访问。‌它是一个整型变量,可以通过特定的操作进行访问和修改。信号量的值可以是0、1或者n,表示可用资源的数量…

一、什么是信号量?

信号量(Semaphore)是一种用于同步和互斥的机制,主要用于控制对共享资源的访问。‌它是一个整型变量,可以通过特定的操作进行访问和修改。信号量的值可以是0、1或者n,表示可用资源的数量。‌

1、信号量的基本概念和作用

信号量可以理解为一个计数器,用于表示可用资源的数量。它通过两个主要操作来实现同步和互斥:

(‌1)P(等待)操作‌:当一个进程或线程需要访问共享资源时,它会尝试执行P操作。如果信号量的值大于0,则进程可以继续访问资源,并将信号量的值减1;如果信号量的值等于0,则进程会被阻塞,直到信号量的值变为正数。

‌(2)V(释放)操作‌:当一个进程或线程完成对共享资源的访问时,它会执行V操作,将信号量的值加1。如果有其他等待进程被阻塞,它们中的一个将被唤醒并获得对资源的访问权限。

二、3个方法和源码分析

iOS中,信号量对于允许多个线程并发访问的资源,它是一个很好的选择。一个初始值为N的信号量允许N+1个线程并发访问(数字是从0开始的)。线程访问资源时,首先获取信号量,即创建信号量,然后等待将信号量的值减1。如果信号量的值小于0,则进入等待状态,否则继续执行。访问资源之后,线程释放信号量,将信号量的值加1。如果信号量的值不小于0,唤醒一个等待中的线程。

1、创建具有初始值的新计数信号量

/*!* @abstract* Creates new counting semaphore with an initial value.* 创建具有初始值的新计数信号量。** @discussion* Passing zero for the value is useful for when two threads need to reconcile* the completion of a particular event. Passing a value greater than zero is* useful for managing a finite pool of resources, where the pool size is equal* to the value.* 当两个线程需要协调特定事件的完成时,值传递零非常有用。传递大于零的值对于管理有限资源池非常有用,其中池大小等于该值。(实际是该值+1)**/
dispatch_semaphore_t
dispatch_semaphore_create(intptr_t value);

2、等待(递减)信号量

/*!* @abstract* Wait (decrement) for a semaphore.* 等待(递减)信号量。** @discussion* Decrement the counting semaphore. If the resulting value is less than zero,* this function waits for a signal to occur before returning. If the timeout is* reached without a signal being received, the semaphore is re-incremented* before the function returns.* 减少计数信号量。如果结果值小于零,他的函数会在返回之前等待信号出现。如果到达超时而没有收到信号,则在函数返回之前,信号量会重新递增。**/
intptr_t
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);

3、释放信号量(增量)

/*!* @abstract* Signal (increment) a semaphore.* 释放信号量(增量)。** @discussion* Increment the counting semaphore. If the previous value was less than zero,* this function wakes a waiting thread before returning.* 增加计数信号量。如果前一个值小于零,他的函数会在返回之前唤醒一个等待的线程。**/
intptr_t
dispatch_semaphore_signal(dispatch_semaphore_t dsema);

4、源码分析(源码地址:https://github.com/swiftlang/swift-corelibs-libdispatch/blob/main/src/semaphore.c)

#pragma mark -
#pragma mark dispatch_semaphore_tdispatch_semaphore_t
dispatch_semaphore_create(intptr_t value)
{dispatch_semaphore_t dsema;// If the internal value is negative, then the absolute of the value is// equal to the number of waiting threads. Therefore it is bogus to// initialize the semaphore with a negative value.if (value < 0) {return DISPATCH_BAD_INPUT;}// 获取类信息,创建一个信号量dsema = _dispatch_object_alloc(DISPATCH_VTABLE(semaphore),sizeof(struct dispatch_semaphore_s));// 设置下一个指针dsema->do_next = DISPATCH_OBJECT_LISTLESS;// 目标队列dsema->do_targetq = _dispatch_get_default_queue(false);// 设置信号量的值dsema->dsema_value = value;// 初始化一个信号_dispatch_sema4_init(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);// 设置原始信号量的值dsema->dsema_orig = value;return dsema;
}void
_dispatch_semaphore_dispose(dispatch_object_t dou,DISPATCH_UNUSED bool *allow_free)
{// 信号量销毁,销毁时,会判断信号量的值dsema_value和原始信号量的值dsema_orig是否相等,如果dsema_value<dsema_orig,那么系统就会认为信号量还在使用中,此时销毁就会发生crash。所以这也是dispatch_semaphore_signal和dispatch_semaphore_wait要成对使用的原因。dispatch_semaphore_t dsema = dou._dsema;if (dsema->dsema_value < dsema->dsema_orig) {DISPATCH_CLIENT_CRASH(dsema->dsema_orig - dsema->dsema_value,"Semaphore object deallocated while in use");}_dispatch_sema4_dispose(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
}size_t
_dispatch_semaphore_debug(dispatch_object_t dou, char *buf, size_t bufsiz)
{dispatch_semaphore_t dsema = dou._dsema;size_t offset = 0;offset += dsnprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ",_dispatch_object_class_name(dsema), dsema);offset += _dispatch_object_debug_attr(dsema, &buf[offset], bufsiz - offset);
#if USE_MACH_SEMoffset += dsnprintf(&buf[offset], bufsiz - offset, "port = 0x%u, ",dsema->dsema_sema);
#endifoffset += dsnprintf(&buf[offset], bufsiz - offset,"value = %" PRIdPTR ", orig = %" PRIdPTR " }", dsema->dsema_value, dsema->dsema_orig);return offset;
}DISPATCH_NOINLINE
intptr_t
_dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema)
{_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);_dispatch_sema4_signal(&dsema->dsema_sema, 1);return 1;
}intptr_t
dispatch_semaphore_signal(dispatch_semaphore_t dsema)
{// 调用os_atomic_inc2o->os_atomic_add2o->os_atomic_add->_os_atomic_c11_op((p), (v), m, add, +)->atomic_fetch_add_explicit,释放资源(release),对信号量加1,返回信号量的值,如果 值>0,未阻塞,正常返回;否则,阻塞,调用函数_dispatch_semaphore_signal_slow,发送一个信号去唤起等待的线程。long value = os_atomic_inc2o(dsema, dsema_value, release);if (likely(value > 0)) {return 0;}if (unlikely(value == LONG_MIN)) {DISPATCH_CLIENT_CRASH(value,"Unbalanced call to dispatch_semaphore_signal()");}return _dispatch_semaphore_signal_slow(dsema);
}DISPATCH_NOINLINE
static intptr_t
_dispatch_semaphore_wait_slow(dispatch_semaphore_t dsema,dispatch_time_t timeout)
{long orig;// 三种超时情况// 1、DISPATCH_TIME_NOW,则表示不等待,这时候会再次尝试获取信号量,如果信号量此时已然小于0,则返回超时提醒,并将信号量的值+1;// 2、DISPATCH_TIME_FOREVER,表示会一直等待被唤醒,调用函数_dispatch_sema4_wait进行等待;// 3、如果是给定的一段时间,走default逻辑,调用函数_dispatch_sema4_timedwait进入计时等待,等线程被唤醒后,返回结果,如果到时间未被唤醒,返回超时;_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);switch (timeout) {default:if (!_dispatch_sema4_timedwait(&dsema->dsema_sema, timeout)) {break;}// Try to undo what the fast path did to dsema->dsema_valueDISPATCH_FALLTHROUGH;case DISPATCH_TIME_NOW:orig = dsema->dsema_value;while (orig < 0) {if (os_atomic_cmpxchgvw2o(dsema, dsema_value, orig, orig + 1,&orig, relaxed)) {return _DSEMA4_TIMEOUT();}}// Another thread called semaphore_signal(). Drain the wakeup.DISPATCH_FALLTHROUGH;case DISPATCH_TIME_FOREVER:_dispatch_sema4_wait(&dsema->dsema_sema);break;}return 0;
}intptr_t
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
{// 调用os_atomic_dec2o->os_atomic_sub2o->os_atomic_sub->_os_atomic_c11_op((p), (v), m, sub, -)->atomic_fetch_sub_explicit,原子操作将当前信号量的值进行-1,并返回值,如果 值>=0,表示有资源可用,正常返回,否则调用_dispatch_semaphore_wait_slow方法进行等待long value = os_atomic_dec2o(dsema, dsema_value, acquire);if (likely(value >= 0)) {return 0;}return _dispatch_semaphore_wait_slow(dsema, timeout);
}

三、方法的基础测试和使用

1、串行队列 + 异步 == 只会开启一个子线程,且队列中所有的任务都是在这个子线程中执行

#pragma mark - 串行队列 + 异步 == 只会开启一个子线程,且队列中所有的任务都是在这个子线程中执行
- (void)test1 {// 串行队列dispatch_queue_t queue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务1:%@",[NSThread currentThread]);});NSLog(@"主线程1");dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务2:%@",[NSThread currentThread]);});NSLog(@"主线程2");dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务3:%@",[NSThread currentThread]);});NSLog(@"主线程3");// 输出结果:主线程1、主线程2、主线程3,同一个子线程,顺序输出:任务1、任务2、任务3
}

2、并行队列 + 异步,会开启不同的子线程,且子线程无序执行

#pragma mark - 并行队列 + 异步,会开启不同的子线程,且子线程无序执行
// 一定要添加“模拟复杂操作”,否则简单的一个输出语句,无法验证“先主,后异步block无序输出”此结果的正确性,
// 猜测:简单的一个输出语句,处理时间太快,时间四舍五入后,输出的结果与理论上的“先主,后异步block无序输出”
// 的结果不一致
- (void)test2 {// 并行队列dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务1:%@",[NSThread currentThread]);});NSLog(@"主线程1");dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务2:%@",[NSThread currentThread]);});NSLog(@"主线程2");dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务3:%@",[NSThread currentThread]);});NSLog(@"主线程3");// 输出结果:主线程1、主线程2、主线程3,不同子线程无序输出:任务1、任务2、任务3
}

3、并行队列 + 异步,用GCD的信号量来实现子线程顺序执行

#pragma mark - 并行队列 + 异步,用GCD的信号量来实现子线程顺序执行
- (void)test3 {// 创建一个信号量,大小为0 / 1 / 2dispatch_semaphore_t sem = dispatch_semaphore_create(0);// 并行队列dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);// dispatch_get_global_queue(0, 0)dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务1:%@",[NSThread currentThread]);// 信号量+1dispatch_semaphore_signal(sem);});NSLog(@"主线程1");// 信号量-1dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务2:%@",[NSThread currentThread]);// 信号量+1dispatch_semaphore_signal(sem);});NSLog(@"主线程2");// 信号量-1dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);dispatch_async(queue, ^{// 模拟复杂操作int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务3:%@",[NSThread currentThread]);});NSLog(@"主线程3");// 信号量大小 == 0 时:// 输出结果:主线程1、任务1、主线程2、任务2、主线程3、任务3,在同一个子线程中输出任务,如果// 使用的是全局队列,可能不是在同一个子线程中输出任务// 信号量大小 == 1 时:// 输出结果:主线程1、主线程2,无序输出:任务1、任务2、主线程3,但 主线程3 永远不会在无序的第一个,// 任务3 永远在最后输出,在不同子线程中输出任务// 信号量大小 >=2 时:// 输出结果:主线程1、主线程2、主线程3,不同子线程无序输出:任务1、任务2、任务3,相当于没有添加信号量// 根据以上测试结果可以更好的理解,// 创建信号量:dispatch_semaphore_create()、// 信号量+1:dispatch_semaphore_signal()、// 信号量-1:dispatch_semaphore_wait()// 这三个方法的含义。
}

四、信号量的场景应用

信号量的应用场景:1、两个请求结果都返回后,再刷新UI;2、并发处理同一个数据;

注:异步block中嵌入另一个异步block模拟数据请求

方法一:(并行队列 + 异步) + 信号量

#pragma mark - 方法一:(并行队列 + 异步) + 信号量
// 任务按照顺序执行,完成后,再刷新UI
- (void)action1 {// 创建一个信号量,大小为0dispatch_semaphore_t sem = dispatch_semaphore_create(0);// 并行队列dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{// 模拟数据请求dispatch_async(queue, ^{int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务1:%@",[NSThread currentThread]);// 信号量+1dispatch_semaphore_signal(sem);});});NSLog(@"主线程1");// 信号量-1dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);dispatch_async(queue, ^{// 模拟数据请求dispatch_async(queue, ^{int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务2:%@",[NSThread currentThread]);// 信号量+1dispatch_semaphore_signal(sem);});});NSLog(@"主线程2");// 信号量-1dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);dispatch_async(dispatch_get_main_queue(), ^{// 主线程刷新UINSLog(@"主线程3,主线程刷新UI");});// 输出结果:主线程1、任务1、主线程2、任务2、主线程3,主线程刷新UI
}

方法二:(并行队列 + 异步组) + dispatch_group_enter、leave(group)对

#pragma mark - 方法二:(并行队列 + 异步组) + dispatch_group_enter、leave(group)对
// 如果不加”dispatch_group_enter、leave(group)对“,输出结果是无序的,
// 且无法得到”两个请求结果都返回后,再刷新UI“的效果。
// 任务按照无序执行,完成后,再刷新UI
- (void)action2 {// 并行队列dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);// 组dispatch_group_t group = dispatch_group_create();// 进入组dispatch_group_enter(group);dispatch_group_async(group, queue, ^{// 模拟数据请求dispatch_async(queue, ^{int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务1:%@",[NSThread currentThread]);// 离开组dispatch_group_leave(group);});});NSLog(@"主线程1");// 进入组dispatch_group_enter(group);dispatch_group_async(group, queue, ^{// 模拟数据请求dispatch_async(queue, ^{int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务2:%@",[NSThread currentThread]);// 离开组dispatch_group_leave(group);});});NSLog(@"主线程2");dispatch_group_notify(group, dispatch_get_main_queue(), ^{// 主线程刷新UINSLog(@"主线程3,主线程刷新UI");});// 输出结果:主线程1、主线程2、无序输出:任务1、任务2,最后输出:主线程3,主线程刷新UI
}

方法三:(并行队列 + 异步组) + 信号量

#pragma mark - 方法三:(并行队列 + 异步组) + 信号量
// 与方法一类似,只是将 异步 换成了 异步组
// 任务按照顺序执行,完成后,再刷新UI
- (void)action3 {// 创建一个信号量,大小为0dispatch_semaphore_t sem = dispatch_semaphore_create(0);// 并行队列dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);// 组dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, queue, ^{// 模拟数据请求dispatch_async(queue, ^{int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务1:%@",[NSThread currentThread]);// 信号量+1dispatch_semaphore_signal(sem);});});NSLog(@"主线程1");// 信号量-1dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);dispatch_group_async(group, queue, ^{// 模拟数据请求dispatch_async(queue, ^{int i = 0;for (int j = 0; j < 100000000; j++) {i += 1;}NSLog(@"任务2:%@",[NSThread currentThread]);// 信号量+1dispatch_semaphore_signal(sem);});});NSLog(@"主线程2");// 信号量-1dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);dispatch_group_notify(group, dispatch_get_main_queue(), ^{// 主线程刷新UINSLog(@"主线程3,主线程刷新UI");});// 输出结果:主线程1、任务1、主线程2、任务2、主线程3,主线程刷新UI
}

整理完成,编辑不易,转载请注明出处,谢谢~~~

http://www.dtcms.com/wzjs/115777.html

相关文章:

  • 网站开发认证考试百度一下搜索网页
  • 外贸网站做推广长沙百度提升排名
  • led行业网站源码台州关键词优化平台
  • 德德模板网站建设步骤企业网站建设专业服务
  • html5移动网站模板盐城seo优化
  • 平台建设网站竞价开户公司
  • 网站访问量怎么赚钱朋友圈产品推广文案
  • 威海网站推广软文范例100字
  • 基础展示营销型型网站关键词制作软件
  • 在线教育网站建设投标书百度高搜
  • 分销网站建设唯尚广告联盟平台
  • 风琴折叠图片效果网站南宁seo计费管理
  • 深圳网站建设lxhdapp推广注册从哪里接单
  • 四川住房和城乡建设九大员网站济南网站建设
  • 做任务悬赏网站爱链接外链购买
  • app store怎么切换地区seo工资
  • 上海外贸seo公司seo有什么作用
  • 各大网站地区是怎样和做的关键词挖掘工具站
  • 误给传销公司做网站算犯罪吗百度seo服务方案
  • 网站开发一般采用什么框架湖南seo优化首选
  • 网站建设推广哪家好免费seo网站诊断
  • 网站制作及实现重庆网站建设推广
  • 常州制作网站价格重庆seo全网营销
  • 做医药中间体的外贸网站友情链接交换网站
  • 网站建设需要哪些成本软文范例大全
  • 微商网站开发合同优化seo软件
  • 网站建设弹窗代码百度指数查询官方网
  • 响应式网站什么意思网站建设的基本
  • 网站建设优化广告流量站长之家备案查询
  • 南宁保洁网站建设百度大数据中心