Domanda

Cosa succede se ho un socket, s, non ci sono dati attualmente disponibili su di esso, è un socket bloccante e io chiamo recv su di esso da due thread contemporaneamente? Uno dei thread otterrà i dati? Lo capiranno entrambi? La seconda chiamata a <=> tornerà con un errore?

È stato utile?

Soluzione

Un thread lo otterrà e non c'è modo di dire quale.

Questo non sembra un design ragionevole. C'è un motivo per cui hai bisogno di due thread che chiamano recv() sullo stesso socket?

Altri suggerimenti

Le implementazioni dei socket dovrebbero essere thread-safe, quindi esattamente un thread dovrebbe ottenere i dati quando saranno disponibili. L'altra chiamata dovrebbe semplicemente bloccare.

Non riesco a trovare un riferimento per questo, ma ecco la mia comprensione:

La garanzia di un fornitore di sicurezza dei thread può significare solo che più thread possono utilizzare in sicurezza i propri propri socket; non garantisce atomicità in una singola chiamata e non promette alcuna allocazione particolare dei dati del socket tra più thread.

Supponiamo che il thread A chiami recv () su un socket che sta ricevendo lo streaming di dati TCP ad alta velocità. Se recv () deve essere una chiamata atomica, il thread A potrebbe bloccare l'esecuzione di tutti gli altri thread, poiché deve essere in esecuzione continuamente per estrarre tutti i dati (fino a quando il suo buffer non è pieno, comunque.) Non sarebbe bene. Quindi, non suppongo che recv () sia immune al cambio di contesto.

Supponiamo invece che il thread A effettui una blocco a recv () su un socket TCP e che i dati arrivino lentamente. Quindi la chiamata a recv () ritorna con errno impostato su EAGAIN.

In uno di questi casi, supponiamo che il thread B chiami recv () sullo stesso socket mentre il thread A sta ancora ricevendo dati. Quando il thread A smette di ricevere dati in modo che il thread B possa iniziare a ricevere i dati? Non conosco un'implementazione Unix che cercherà di ricordare che il thread A era nel mezzo di un'operazione sul socket; invece, spetta all'applicazione (thread A e B) negoziarne l'uso.

In generale, è meglio progettare l'app in modo che solo uno dei thread chiamerà recv () su un singolo socket.

Dalla pagina man su recv

  

Un recv () su un socket SOCK_STREAM   restituisce quante più informazioni disponibili   come può la dimensione del buffer fornito   tenere.

Supponiamo che tu stia utilizzando TCP, poiché non è stato specificato nella domanda. Supponiamo quindi di avere il thread A e il thread B entrambi bloccati su recv () per socket s. Una volta che s ha ricevuto alcuni dati, sbloccherà uno dei thread, diciamo A e restituirà i dati. I dati restituiti avranno una dimensione casuale per quanto ci riguarda. Il thread A controlla i dati ricevuti e decide se ha un & Quot; message & Quot ;, in cui un messaggio è un concetto a livello di applicazione.

Il thread A decide che non ha un messaggio completo, quindi chiama di nuovo recv (). MA nel frattempo B stava già bloccando sullo stesso socket e ha ricevuto il resto del & Quot; messaggio & Quot; che era inteso per il thread A. Sto usando inteso vagamente qui.

Ora sia il thread A che il thread B hanno un messaggio incompleto e, a seconda di come viene scritto il codice, gettano i dati come non validi o causano errori strani e sottili.

Vorrei poter dire di non saperlo per esperienza.

Quindi, mentre recv () stesso è tecnicamente sicuro per i thread, è una cattiva idea avere due thread che lo chiamano contemporaneamente se lo si utilizza per TCP.

Per quanto ne so, è completamente sicuro quando si utilizza UDP.

Spero che questo aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top