I just duplicate data (filter/shaper coeffs), that way, nobody is waiting for filter handoff and I don't need locking. When the UI changes something, I set a flag that the audio filters need updating, but the audio thread does this when it gets to it. The coeffs of the audio filter instance get updated in the audio thread only. And the gfx ones in the gfx thread only. Pseudo objects make this pretty easy. Can just reuse the same functions
Usually locking is best avoided when reasonably possible I think.