Я думаю, вы можете поступать неправильно. Сериализация каждого вызова метода будет «своего рода» работать, но она не будет надежно обрабатывать такие операции, как добавление или удаление объекта User. Например, если ваш основной поток удаляет объект User, не имеет значения, что сетевой поток тщательно блокирует мьютекс, потому что после возврата операции mutex-lock сетевой поток будет пытаться получить доступ к (теперь удаленному) пользователю объект, и попытка чтения или записи свободной памяти приведет к сбою вашего приложения (или, что еще хуже, просто таинственно делает неправильные вещи).
Вот лучший способ сделать это (предполагая, что объекты User достаточно малы): вместо того, чтобы сетевой поток и поток ввода-вывода совместно использовали один и тот же объект User, и пытался сериализовать все обращения к объекту на На уровне метода вам лучше отдать отдельную копию каждого объекта User потоку ввода-вывода. Затем, когда один поток изменяет свою локальную копию объекта User, он должен отправить сообщение другому потоку, содержащее копию обновленного объекта, и, когда другой поток получает сообщение, он может обновить свою локальную копию для повторного сопоставления. Таким образом, каждый поток имеет эксклюзивный доступ на чтение / запись к своему локальному набору пользовательских объектов и может читать / писать их без какой-либо блокировки. Это также позволяет каждому потоку добавлять или удалять объекты по своему желанию (при условии, что впоследствии он отправляет сообщение обновления другому потоку, поэтому другой поток будет следовать его примеру).