This is the 23rd day of my participation in the August More Text Challenge
We continue our analysis of locks in iOS.
Structure of SyncData in synchronized
Let’s take a look at the data structure SyncData inputs:
SyncData
Is a struct type of data; We notice that there’s one inside the structureSyncData* nextData
Member variables, see here, we will subconsciously think of linked lists. Because there’s only onenextData
So it could be aSingly linked list
;DisguisedPtr<objc_object> object;
We’re learningassociations
I saw a code like this at the time, is aptr
Type encapsulation;threadCount
How many threads are using thisblock
;recursive_mutex_t mutex;
Is aRecursive locking
, can only be used recursively, but not multithreaded recursion;
Now that we know the data structure of SyncData, let’s look at the ID2Data method;
Synchronized data structure
TLS thread related knowledge supplement
Before talking about id2DATA method, we need to supplement the relevant knowledge of TLS;
Thread Local Storage, TLS: a private space provided by the operating system for threads, usually with limited capacity. Linex typically operates through the following functions in the pThread library:
- pthread_key_create()
- pthread_getspecific()
- pthread_setspecific()
- pthread_key_delete()
Id2data method analysis
Let’s click on the implementation of the ID2Data method, which is quite complex, so let’s close the complex operation and take a look at the method as a whole:
We can find that the id2data method mainly does the following operations:
data
storage- Open up memory space. Here
SyncData
The type ofresult
The assignment; lock()
andunlock()
Is to ensure the thread safety when the method body internal memory opening; It has nothing to do with the external lock;- And finally return a
result
;
Next, we carry out detailed analysis:
spinlock_t *lockp = &LOCK_FOR_OBJ(object);
Through the macro#define LOCK_FOR_OBJ(obj) sDataLists[obj].lock
andobject
Acquired a lock;SyncData **listp = &LIST_FOR_OBJ(object);
Through the macro#define LIST_FOR_OBJ(obj) sDataLists[obj].data
andobject
Got aSyncData
;
So we have to ask: what is the use of getting listP? What are sDataLists in macro definitions?
SDataLists structure analysis
When we learned about hash tables, we used to get indices based on hash functions, and then hash if there was a conflict; So now in addition to hashing, there’s a zipper method;
First, sDataLists are a global static variable and hash table that are used throughout SyncData processing. The underlying generic is SyncList, which also contains SyncData:
In order to analyze its specific structure, we use the following code, combined with LLDB for analysis:
Note that we use an infinite loop of do-while at the end of the main method to hold the App, otherwise the direct program will end;
We use p sDataLists to view the sDataLists data structure. After printing, we find that the sDataLists structure contains an array structure, and the array has 64 elements. Because we are using the simulator, there are 64 structures after printing, and the 64 here comes from:
There are 64 emulators and 8 real ones;
Next, we let id2data execute once (storing a SyncData in sDataLists) and interrupt the second execution:
It is found that the first SyncData object stored is stored at position 23 (because it is a hash structure, the first SyncData object does not start at 0, but is stored with a calculated index).
Its structure is as follows:
SyncData
inSyncList
;SyncList
inarray
In the table.
Its data structure is roughly as follows (we use 8 real machines to illustrate) :
We like to pass self when we use @synchronized, so if we pass self when we call @synchronized twice, then the two SyncData generated by the first and second self will generate hash conflicts. SyncList is a linked list. The storage structure will become:
- The same
self
The two generatedSyncData
It’s not going to collide, it’s going to be stored in the linked listSyncList
; - two
SyncData
Have similarity;
Linked list structure is not convenient to query, and SyncData does not need to query, only need to lock unlock, that is, only need to add and delete operations (zipper method);
To be continued……