Skip to content

avoiding thread-unsafe code with BitArray #40096

@goretkin

Description

@goretkin

I had an unpleasant experience using some multithreaded code that was writing into a BitArray that had been constructed using similar on another array that was the result of broadcasting:

julia> map(iseven, 1:4)
4-element Array{Bool,1}:
 0
 1
 0
 1

julia> iseven.(1:4)
4-element BitArray{1}:
 0
 1
 0
 1

It has been documented that setindex!(::BitArray, ...) is not thread-safe. However, BitArray arises whenever broadcasting produces an array with eltype(array) == Bool, and so I think it is easy to not be aware of this issue. Personally, I have an easy time being suspicious of BitArray in threaded code, even without the explicit warning. Yet it still did not initially occur to me that I should look for a BitArray when I was experiencing a race condition. I did not even remember that there were BitArray values in my code.

Some ideas that may have helped me in this case:

  1. Broadcasting never produces BitArrays (I was originally going to title this issue "consider Array{Bool} in place of BitArray for broadcasting result")
    Or, it produces some read-only version of BitArray.
  2. similar returns Array{Bool} even for BitArray input
    Or it has an extra argument to return an array of a type that is "more" thread safe.
  3. there is some trait defined like
isthreadsafe(typeof(setindex!), ::BitArray, args...) = NoItIsNot()
isthreadsafe(typeof(setindex!), ::Array, args...) = YesItIsIndeed()
# ...

And users can use it to define generic code, or it could be checked automatically by a macro that does threading.
(related https://github.com/JuliaArrays/ArrayInterface.jl)

Metadata

Metadata

Assignees

No one assigned

    Labels

    arrays[a, r, r, a, y, s]multithreadingBase.Threads and related functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions