-
Notifications
You must be signed in to change notification settings - Fork 255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Python thread accesses Java instance in another thread #588
Comments
Hello pyjnius maintainers, I am also running into this issue. Would anyone have a chance to have a look ? |
Hi team, do you have any updates about this? |
Hi team, I've also faced this issue. Here is the minimal reproducible example, import jnius
import threading
def do_job(tid):
cls = jnius.autoclass('java.lang.String')
print(f"thread: {tid}, Id: {cls} | {id(cls)}")
def main():
jnius.autoclass('java.lang.String') # comment out this line to make ids different
threads = []
for i in range(10):
t = threading.Thread(target=do_job, args=(i,))
t.start()
threads.append(t)
for t in threads:
t.join()
if __name__ == '__main__':
main() If you comment out the marked line, the code becomes partially* thread safe. The ids will be different. However, if you first instantiated a Java class in the main thread, all the threads reuse this instance. Thus, the ids will be the same.
|
More complicated snippet using ArrayList import jnius
import threading
from queue import Queue
def do_job(tid, q):
ArrayList = jnius.autoclass('java.util.ArrayList')
arraylist = ArrayList()
arraylist.add(tid)
arraylist.set(0, arraylist.get(0))
q.put((tid, arraylist))
def do_job_passed(tid, q):
ArrayList = jnius.autoclass('java.util.ArrayList')
arraylist = ArrayList()
arraylist.add(tid)
a = arraylist.get(0) # use a trick with assigning an explicit memory address
arraylist.set(0, a)
q.put((tid, arraylist))
def main():
jnius.autoclass('java.util.ArrayList') # comment out this line to fix mutability or use do_job_passed
queue = Queue()
threads = []
ref_ints = list(range(100))
ints = [None] * 100
for i in ref_ints:
t = threading.Thread(target=do_job, args=(i, queue))
t.start()
threads.append(t)
for t in threads:
tid, arraylist = queue.get()
t.join()
ints[tid] = arraylist.get(0)
if ints != ref_ints:
print(ints)
print(ref_ints)
for j, (i, ri) in enumerate(zip(ints, ref_ints)):
if i != ri:
print(f"index {j}, expected {ri}, actual {i}")
raise ValueError("ints != ref_ints")
if __name__ == '__main__':
main() |
Has anyone found any solutions to this problem? |
@TheCreatorAMA class ClassA {
public Object b(Object arg1, Object arg2, ...) {
return ...;
}
public static Obect b(ClassA instance, Object arg1, Object arg2, ...) {
return instance.b(arg1, arg2, ...);
}
} Then, you should invoke |
Environment
Expected behavior
In the case of multithreading of Python, a Java instance created in a Python thread should not be accessed from another Python thread.
Observed behavior
A Java instance created in a Python thread is accessed from another Python thread.
How to reproduce
sample code: https://github.com/akiou/pyjnius_multithreading
In the sample code, a Python process creates multiple threads, and each thread creates an Java instance and invokes its methods. Although a python thread must create and use only one java instance, the
validate()
method is occasionally invoked from different python thread.You need to execute the python script
test.py
in the sample code multiple times to reproduce this error because I don't know when this error can be occurred.The text was updated successfully, but these errors were encountered: