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:

  • SyncDataIs a struct type of data; We notice that there’s one inside the structureSyncData* nextDataMember variables, see here, we will subconsciously think of linked lists. Because there’s only onenextDataSo it could be aSingly linked list;
  • DisguisedPtr<objc_object> object;We’re learningassociationsI saw a code like this at the time, is aptrType encapsulation;
  • threadCountHow 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:

  • datastorage
  • Open up memory space. HereSyncDataThe type ofresultThe 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 aresult;

Next, we carry out detailed analysis:

  • spinlock_t *lockp = &LOCK_FOR_OBJ(object);Through the macro#define LOCK_FOR_OBJ(obj) sDataLists[obj].lockandobjectAcquired a lock;
  • SyncData **listp = &LIST_FOR_OBJ(object);Through the macro#define LIST_FOR_OBJ(obj) sDataLists[obj].dataandobjectGot 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:

  • SyncDatainSyncList;
  • SyncListinarrayIn 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 sameselfThe two generatedSyncDataIt’s not going to collide, it’s going to be stored in the linked listSyncList;
  • twoSyncDataHave 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……