Multi-threading won't solve this for you. Web Workers are as mentioned already, limited and does not add any benefits in this context as that would require access to DOM etc. (you could use them to process pixels using transferable objects, ie. typed arrays, but you would have to pipe them back to your main JS thread after processing so you would be just as far).
Good news though, you can draw two different paintings at the same time. I assume you use canvas to achieve this.
Simply create two overlaying canvases and feed your local mouse/touch movements to one of the canvases while feeding the data over your web socket to the other canvas.
The other way is to draw each segment in an atomic manner - for each mouse move and for each data received over web socket representing a movement (you may need to iterate here), for example:
ctx.beginPath(); /// reset path for this segment
ctx.moveTo(oldX, oldY); /// of current client/user
ctx.lineTo(x, y); /// current position
ctx.strokeStyle = currentColor; /// the one drawing this line
ctx.stroke();
(oldX/Y would be initialized the first time by the mouse down event).
Doing this in a segmented way allows both to draw at the same time, albeit it's a bit more performance hungry. Personally I would go for a layered canvas solution if order of lines isn't important. As your solution would use events it would be asynchronous and would deal with an event queue which should work fine here.
Simply set up some arrays to hold the data (old position, styles etc.) for each user so you can use an ID/index for the current user/client.
Some pseudo code to give a simple overview for segmented approach:
var oldX = [],
oldY = [],
currentColor = [], ...;
...set up clients, arrays, mousedown/up etc.
canvas.onmousemove = function(e) {
var pos = getMousePos ...
if (isDrawing) drawSegment(0, pos.x, pos.y); /// f.ex. client 0 = local
}
function handleSocketData() {
... get x/y from data stream
drawSegment(1, x, y); /// f.ex. client 1 = web socket
}
function drawSegment(client, x, y) {
ctx.beginPath();
ctx.moveTo(oldX[client], oldY[client]);
ctx.lineTo(x, y);
ctx.strokeStyle = currentColor[client];
ctx.stroke();
oldX[client] = x;
oldY[client] = y;
}
This is of course simplified. You would need to store each point in a point array with the same state details as when drawn to be able to redraw the canvas if cleared, handle multiple segments on the socket and so forth but I think it gives an impression of how to implement the core principle of this method.
Hope this helps!