Are you making a device driver? Or just an app interfacing with a device that already has a way of sending the data to your application layer? Do you want to do this in C, C++, Obj-C, Swift, (…)?
For thread synchronisation more generally you can look into the Grand Central Dispatch APIs. They have Dispatch Groups - you can for instance schedule this all to happen on the main thread but as two async jobs on the main thread, or use synchronisation primitives like channels to inform when one thread is ready for the other to continue.
You also have something like NSCondition that can lock and wait on a predicate returning true. You also have NSLock. These are both POSIX style mechanisms. - If you're in the world of Swift you can adopt Structured Concurrency and the Actor model.
If the device submits its data through a file descriptor you can use Dispatch Sources to monitor and act on changes there.
With Dispatch Queues you can set it up in such a way that once there is new data, you place the data task on the queue and it starts the processing task.
If you need these things to be able to run as entirely separate processes, there's also NSDistributedLock that will use the file system as its Mutex and can thus coordinate between several applications looking out for a specific "locking" file
In short there are many ways of designing such a system with different tradeoffs