Why would MySQL request a shared-lock after setting transaction level to READ UNCOMMITTED
"Read chunks, but only update a few of them"...

SELECT a chunk -- separate transaction, don't care about locking, etc
munch on that chunk to figure out the 'few' ids to update
BEGIN;
    SELECT ... WHERE id IN (list of the few) FOR UPDATE;
    minimal other work
    UPDATE them;
COMMIT;   -- plus checks for deadlocks, etc, and restart the code.


The idea is to pull as much time-consuming code out of the transaction as possible, thereby making the transaction faster, thereby minimizing the likelihood of conflict.  (No, it probably won't eliminate all deadlocks, but it should help.)

Another note:  If possible, go through the table in the same order in all threads.  Deadlocks happen when one thread plays with id IN (1,2) but another does IN (2,1).  If both do IN (1,2), then you get delays, not deadlocks.

Another tip:  Make the chunks smaller.