This is the 18th day of my participation in the August Challenge

review

In the last blog has made a basic introduction to the GCD fence function, there are application examples and the underlying source code for analysis, this blog will explore the semaphore analysis!

Multithreading in iOS (I) – Processes and threads

IOS low-level exploration of multithreading (II) – Threads and locks

IOS low-level exploration of multithreading (3) – GCD

IOS low-level exploration of multithreading (4) – GCD queue

IOS bottom exploration of multithreading (five) – GCD different queue source analysis

IOS bottom exploration of multithreading (six) – GCD source analysis (sync function, async asynchronous function)

IOS low-level exploration of multithreading (seven) – GCD source analysis (cause of deadlock)

IOS bottom exploration of multithreading (eight) – GCD source analysis (function synchronization, asynchrony, singleton)

IOS bottom exploration of multithreading (nine) – GCD source analysis (fence function)

1. The semaphore

1.1 Semaphore introduction

A Semaphore in GCD is a Dispatch Semaphore, which is something that holds a count of signals. There are three methods.

  • dispatch_semaphore_create: Creates a semaphore
  • dispatch_semaphore_wait: Semaphore waiting
  • dispatch_semaphore_signal: Semaphore release

1.2 Semaphore examples

In the concurrent queue, you can use semaphore control, the maximum number of concurrent, as follows:

  • Semaphore example print results

There are four tasks created and executed asynchronously. When I created the semaphore, I set the maximum number of concurrent tasks to 2

  dispatch_queue_t queue = dispatch_get_global_queue(0.0);
    dispatch_semaphore_t sem = dispatch_semaphore_create(2);
Copy the code

From the running GIF, it can be seen that two tasks are executed together each time, and the printed result is clear at a glance.

For another example, what if you set the semaphore concurrency to zero?

Set the semaphore concurrency to0Is the equivalent of locking,dispatch_semaphore_waitblockedTask 1Let it wait and waitTask 2And when it’s done,dispatch_semaphore_signalSend the signal! I’m done! You do it!

So how does a semaphore wait and send a signal?

2. Semaphore analysis

Look at the description of the API for dispatch_semaphore_create

  • Passed for this value when two threads need to coordinate the completion of a particular event0Is very useful.
  • Pass is more than0The value of is useful for managing finite resource pools whose size is equal to this value.
  • The starting value of the semaphore. Transmission is less thanThe starting value of the semaphore. Passing a value less than zero causes NULL to be returned.Will result in a returnNULLWhich is less than0It’s not going to work.

In summary, you can control the maximum number of concurrent threads in the thread pool

2.1 dispatch_semaphore_signal

  • dispatch_semaphore_signal

  • indispatch_semaphore_signalinsideos_atomic_inc2oAtomic operations add themselves1And then it decides ifvalue > 0, will return0.
  • For example,valueadd1 And then it’s still less than 0That means it’s aA negative number, which is calleddispatch_semaphore_waitToo many times,dispatch_semaphore_waitIt’s subtracting, and we’ll look at that later.
  • It’s still going to be less than that0So unusual"Unbalanced call to dispatch_semaphore_signal(), and then calls_dispatch_semaphore_signal_slowMethod, do fault tolerant processing,_dispatch_sema4_signalIs ado whilecycle
_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;
}
Copy the code
  • _dispatch_sema4_signal
void
_dispatch_sema4_signal(_dispatch_sema4_t *sema, long count)
{
	do {
		int ret = sem_post(sema);
		DISPATCH_SEMAPHORE_VERIFY_RET(ret);
	} while (--count);
}

Copy the code

2.2 dispatch_semaphore_wait

  • dispatch_semaphore_wait

dispatch_semaphore_wait The source code is as follows:

  • os_atomic_dec2oAtomic subtraction1Operation, that is, rightvalueValue is subtracted to control the number of concurrent requests.
  • If the number of concurrent requests is2Is changed to after the method is called1, indicates that the number of concurrent requests is1And the rest can be executed simultaneously1A task. If the initial value is zero0After subtracting operations, isA negative numberIs called_dispatch_semaphore_wait_slowMethods.

The _dispatch_semaphore_wait_slow method is as follows:

  • _dispatch_semaphore_wait_slow

  • Here todispatch_time_t timeoutTo do the judgment processing, which we passed in the previous exampleDISPATCH_TIME_FOREVER, then will call_dispatch_sema4_waitmethods
void
_dispatch_sema4_wait(_dispatch_sema4_t *sema)
{
	kern_return_t kr;
	do {
		kr = semaphore_wait(*sema);
	} while (kr == KERN_ABORTED);
	DISPATCH_SEMAPHORE_VERIFY_KR(kr);
}

Copy the code

Inside the _dispatch_sema4_wait method is a do-while loop that continues until the condition is met, causing the process to block. This explains the execution results in the example above.

The example above is equivalent to the picture below

In the box above, ① is equivalent to ②, where the do-while loop executes task 2, and task 1 waits in a loop.

3. Summary

  • dispatch_semaphore_wait Semaphore wait, internal is the number of concurrent subtractive operation, if is less than 0, will perform_dispatch_semaphore_wait_slowAnd then call_dispatch_sema4_waitIs ado-whileAnd ends the loop until the condition is met
  • dispatch_semaphore_signalThe semaphore is released, and internally the number of concurrent operations is added until greater than0Is operable
  • keepThread synchronizationThat will beAsynchronous executionTask conversion toSynchronous executiontask
  • ensureThread safetyforThread lock, which is equivalent toThe mutex

More content continues to be updated

🌹 if you like, give it a thumbs up 👍🌹

🌹 feel harvest, can come to a wave, collection + attention, comment + forward, so as not to find me next time 😁🌹

🌹 welcome everyone to leave a message exchange, criticism and correction, learn from each other 😁, improve themselves 🌹