Well, the synchromization is quite a large topic itself. Start with the boost documentation.
In simpliest case, when you have one reader and one writer you may use boost::mutex object and boost::unique_lock guard object inside your reader and write functions.
class HapticDevice {
...
protected:
boost::muitex _mutex;
....
}
Somewhere in reader or writer function:
boost::unique_lock<boost::mutex> _guard(hapticDeviceObject->_mutex);
Which is in generally a bad code style. Depending on your algorithm, you rather create functions to add data, something like HapticDevice::addDeviceData(const &DeviceData), and retrieve data, like HapticDevice::getDeviceData(), and do all the required locking inside them.
The unique_lock guard object is needed to release mutex when executions goes out of reader or writer functions (like an exception or just end of the function).
If you have concurent readers you may consider using shared_lock for them to increase performance.