I have a class that has a nullable variable that is written by multiple thread, something like
class A {
var s: String? = null //var accessed by multiple threads
fun doStuff() {
if (s != null) {
//not safe
}
}
}
To counter this, I usually make an immutable copy like so
class A {
var s: String? = null //var accessed by multiple threads
fun doStuff() {
val sCopy = s
if (sCopy != null) {
//safe now
}
}
}
I read about concurrency tools like volatile, synchronized etc but I'm not good at multithreading yet to know how should I handle it and I'm pretty sure there is better ways to achieve this than creating an immutable value, how would you do it?
You can simply reuse Java tooling in these cases.
For most simple cases, you would create an object (can be of any type) that will be used as the lock and use that lock for every single access to your state. There's the synchronized function which even let's you return a value directy:
val anyLock = Any()
fun syncWithArbitraryObjTest(): Int = synchronized(anyLock) { 123 }
Note that synchronized is a function in Kotlin which returns a value. This makes it more powerful than Java's synchronized keyword. Technically it doesn’t make a difference on which object you lock, as long as you use the same object for all relevant code blocks that need be synchronized with each other.
If you choose to use a specific Lock object, e.g. an instance of ReentrantLock, you may use withLock instead:
val lock = ReentrantLock()
fun syncWithLockTest(): Int = lock.withLock { 123 }
Last but not least, your code val sCopy = s is no copy of s, it's simply a second variable pointing to the same object; this code isn't any safer.
You need to lock both the writes and the reads to your variable, like this:
class A {
var s: String? = null //var accessed by multiple threads
set(s) {
synchronized(this) {
field = s
}
}
fun doStuff() {
synchronized(this) {
//safe now
}
}
}
You need the synchronized in the setter beacuse otherwise the value might be overwritten while a thread is in doStuff.
Though in general it's better to avoid situations where multiple threads can write the same variable.
Related
I'm new with kotlin I'm trying to run several requests to a web in parallel threads
so far I got
class HttpClient {
private val DEFAULT_BASE_URL = "https://someapi"
fun fetch(endPoint: String, page: Int): String {
FuelManager.instance.basePath = DEFAULT_BASE_URL
val (_, response, _) = endPoint.httpGet(listOf("page" to page)).response()
return String(response.data)
}
fun headers(endPoint: String): Headers {
FuelManager.instance.basePath = DEFAULT_BASE_URL
val (_, response, _) = endPoint.httpGet(listOf("page" to 1)).response()
return response.headers
}
}
and the class that runs the whole process
class Fetcher(private val page: Int) {
suspend fun run(): String = coroutineScope {
async {
HttpClient().fetch(DEFAULT_ENDPOINT, page)
}
}.await()
companion object {
private const val DEFAULT_ENDPOINT = "endpoint"
suspend fun fetchAll(): MutableList<String> {
val totalThreads = (totalCount() / pageSize()) + 1
return runBlocking {
var deck: MutableList<String> = mutableListOf()
for (i in 1..totalThreads) {
deck.add(Fetcher(i).run())
}
deck
}
}
private fun pageSize(): Int {
return HttpClient().headers(DEFAULT_ENDPOINT)["page-size"].first().toInt()
}
private fun totalCount(): Int {
return HttpClient().headers(DEFAULT_ENDPOINT)["total-count"].first().toInt()
}
}
}
I'm looking to mirror the Thread.join() from Java. Could you give me some pointers on how to improve my code to achieve that?
Also if not much asking, could you suggest a book/example set on this subject?
Thanks for your help in advance!
A few points:
If you're going to be using coroutines in a project, you'll mostly want to be exposing suspending functions instead of blocking functions. I don't use Fuel, but I see it has a coroutines library with suspend function versions of its blocking functions. Usually, suspend functions that unwrap an asynchronous result have the word "await" in them. I don't know for sure what response() is since I don't use fuel, but if I had to guess, you can use awaitResponse() instead and then make the functions suspend functions.
Not related to coroutines, but there's almost no reason to ever use the String constructor to wrap another String, since Strings are immutable. (The only reason you would ever need to copy a String in memory like that is maybe if you were using it in some kind of weird collection that uses identity comparison instead of `==`` comparison, and you need it to be treated as a different value.)
Also not related to coroutines, but HttpClient in your case should be a singleton object since it holds no state. Then you won't need to instantiate it when you use it or worry about holding a reference to one in a property.
Never use runBlocking in a suspend function. A suspend function must never block. runBlocking creates a blocking function. The only two places runBlocking should ever appear in an application are at the top level main function of a CLI app, or in an app that has both coroutines and some other thread-management library and you need to convert suspend functions into blocking non-suspend functions so they can be used by the non-coroutine-based code.
There's no reason to immediately follow async() with await() if you aren't doing it in parallel with something else. You could just use withContext instead. If you don't need to use a specific dispatcher to call the code, which you don't if it's a suspend function, then you don't even need withContext. You can just call suspend functions directly in your coroutine.
There's no reason to use coroutineScope { } to wrap a single child coroutine. It's for running multiple child coroutines and waiting for all of them.
So, if we change HttpClient's functions into suspend functions, then Fetcher.run becomes very simple.
I also think that it's kind of weird that Fetcher is a class with a single property that is only used in a one-off fashion with its only function. Instead, it would be more straight-forward for Fetcher to be a singleton object and for run to have the parameter it needs. Then you won't need a companion object either since Fetcher as an object can directly host those functions.
Finally, the part you were actually asking about: to run parallel tasks in a coroutine, use coroutineScope { } and then launch async coroutines inside it and await them. The map function is handy for doing this with something you can iterate, and then you can use awaitAll(). You can also get totalCount and pageSize in parallel.
Bringing that all together:
object HttpClient {
private val DEFAULT_BASE_URL = "https://someapi"
suspend fun fetch(endPoint: String, page: Int): String {
FuelManager.instance.basePath = DEFAULT_BASE_URL
val (_, response, _) = endPoint.httpGet(listOf("page" to page)).awaitResponse()
return response.data
}
suspend fun headers(endPoint: String): Headers {
FuelManager.instance.basePath = DEFAULT_BASE_URL
val (_, response, _) = endPoint.httpGet(listOf("page" to 1)).awaitResponse()
return response.headers
}
}
object Fetcher() {
suspend fun run(page: Int): String =
HttpClient.fetch(DEFAULT_ENDPOINT, page)
private const val DEFAULT_ENDPOINT = "endpoint"
suspend fun fetchAll(): List<String> {
val totalThreads = coroutineScope {
val totalCount = async { totalCount() }
val pageSize = async { pageSize() }
(totalCount.await() / pageSize.await()) + 1
}
return coroutineScope {
(1..totalThreads).map { i ->
async { run(i) }
}.awaitAll()
}
}
private suspend fun pageSize(): Int {
return HttpClient.headers(DEFAULT_ENDPOINT)["page-size"].first().toInt()
}
private suspend fun totalCount(): Int {
return HttpClient.headers(DEFAULT_ENDPOINT)["total-count"].first().toInt()
}
}
I changed MutableList to List, since it's simpler, and usually you don't need a MutableList. If you really need one you can call toMutableList() on it.
To restate the title, I'm wondering if there is a way to convert the MyThread class below to a Kotlin Coroutine.
If you look closely, you will notice that the MyThread class has a property variable called someObject that can be modified from inside the both the run and the cancel methods. In this case SomeObject is completely encapsulated inside MyThread and I want to keep it that way. Is there a way to convert MyThread to a coroutine or do I already have the most elegant version of the code?
class MyCancellable: Thread(){
val someObject= SomeObject()
override fun run() {
super.run()
while(someObject.keepGoing){
someObject.value++
}
}
fun cancel(){
someObject.keepGoing=false
}
}
A reusable coroutine is a suspend function where the only parameter is CoroutineScope, so something roughly equivalent to what you have is:
fun CoroutineScope.cancellableCounter() = withContext(Dispatchers.Default) {
val someObject = SomeObject()
while (someObject.keepRunning) {
yield()
someObject.value++
}
}
The function can be called from inside another coroutine, or it can be passed to async or launch, such as myScope.launch(::cancellableCounter). The returned Job can be cancelled by calling cancel() on it.
But as mentioned in the comments, there may be a better way to design it depending on how SomeObject is supposed to be used.
Edit: Maybe for the ServerSocket you'd need to do something like this. I haven't tested it, so not totally sure. But I don't think you want to directly call accept() in a coroutine because it blocks for potentially a long time and does not cooperate with cancellation. So I'm suggesting you still need a dedicated thread. suspendCancellableCoroutine can bridge this to a suspend function.
suspend fun awaitSomeSocket(): Socket = suspendCancellableCoroutine { continuation ->
val socket: ServerSocket = generateSocket()
continuation.invokeOnCancellation { socket.close() }
thread {
runCatching {
val result = socket.use(ServerSocket::accept)
continuation.resume(result)
}
}
}
I think you want a class that can start its own coroutine? That seems like the equivalent, something like:
class MyCancellable(private val scope: CoroutineScope) {
private var job: Job? = null
val someObject = SomeObject()
fun run() {
if (job != null) return
job = scope.launch {
while(someObject.keepGoing) {
someObject.value++
}
}
}
fun cancel() {
someObject.keepGoing = false
}
}
Typically you'd do job.cancel() instead, and check isActive in the while loop - I don't think it matters here, but it might be worth doing it "properly" (and it is technically different to someObject.keepGoing going false for some other reason). And if you're doing that, maybe TenFour04's suggestion is better, since the only reason you need a class/object is so you can put externally visible run and cancel functions in it. If the coroutine just runs anyway, and you call cancel on the Job it returns, it's all good!
I have a GLib.List to which I want to add elements.
I want to add those elements concurrently using multiple GLib.Threads
I'm trying to synchronize access to the list using a GLib.Mutex. Synchronization seems to work but no elements are added.
public static void main() {
var list = new GLib.List<string>();
var mutex = GLib.Mutex();
var workerA = new Worker("A", list, mutex);
var workerB = new Worker("B", list, mutex);
var workerC = new Worker("C", list, mutex);
GLib.Thread<void*> tA = new GLib.Thread<void*>("WorkerThread", workerA.run);
GLib.Thread<void*> tB = new GLib.Thread<void*>("WorkerThread", workerB.run);
GLib.Thread<void*> tC = new GLib.Thread<void*>("WorkerThread", workerC.run);
tA.join();
tB.join();
tC.join();
stdout.printf("List:\n");
foreach (string str in list) {
stdout.printf(" - %s\n", str);
}
}
class Worker : GLib.Object {
private string name;
private weak GLib.List<string> list;
private weak GLib.Mutex mutex;
public Worker(string name, GLib.List<string> list, GLib.Mutex mutex) {
this.name = name;
this.list = list;
this.mutex = mutex;
}
public void* run() {
mutex.lock();
list.append(name);
mutex.unlock();
return null;
}
}
When I look at the synchronization part it seems to work right (even with many more Threads), but no elements get added to the list!
Output:
List:
Can somebody please tell me how to do this ?
GLib.List is a little weird. The append method actually modifies the pointer list, not the thing it is pointing to. If you want this to work you need to either:
Put the list in a shared place (e.g., make it a field of a class that all the threads share or a global variable).
Use Gee.List from the libgee package instead. In general, the data structures in libgee are much easier to use in Vala than their counter parts in glib.
Thanks to apmasell pointing out the thing not working is actually GLib.List I took a look at the C source code.
He's right: The append method modifies the pointer - but only (!) if the GLib.List is empty!
So Apart from making the list a global variable or using another list implementation I think the best work workaround is to simply add one element before passing the list to a thread.
After all threads are done you can simply remove the element again.
I know that this subject is slightly "Played Out", but I am still terribly confused. I have a class with properties that will be updates by multiple threads and I am trying to allow the properties to be updated in a Threadsafe manner.
Below, I have included a few examples of what I have tried thus far (the class is contained within a BindingList so its properties call a PropertyChangingEventHandler event).
Method 1 - Doubles
private double _Beta;
public double Beta
{
get
{
return _Beta;
}
}
private readonly BetaLocker = new object();
public void UpdateBeta(double Value)
{
lock (BetaLocker)
{
_Beta = Value;
NotifyPropertyChanged("Beta");
}
}
Method 2 - Ints
private int _CurrentPosition;
public int CurrentPosition
{
get
{
return _CurrentPosition;
}
}
public void UpdatePosition(int UpdateQuantity)
{
Interlocked.Add(ref _CurrentPosition, UpdateQuantity);
NotifyPropertyChanged("CurrentPosition");
}
Basically - is the current way that I am creating properties completely threadsafe for both ints and doubles?
You have to ask yourself what it means to be Thread Safe (yes, it's a link to wikipedia and it's blacked out ^_^):
A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time. There are various strategies for making thread-safe data structure
So now you have to determine if your code guarantees safe execution if executed by multiple threads: the quick answer is that both of your code samples are thread safe! However (and this is a big one), you also have to consider the usage of the object and determine if it is Thread Safe also... here is an example:
if(instance.Beta==10.0)
{
instance.UpdateBeta(instance.Beta*10.0);
}
// what's instance.Beta now?
In this case you have absolutely no guarantee that Beta will be 100.0 because beta could have changed after you checked it. Imagine this situation:
Thread 2: UpdateBeta(10.0)
Thread 1: if(Beta == 10.00)
Thread 2: UpdateBeta(20.0)
Thread 1: UpdateBeta(Beta*10.0)
// Beta is now 200.0!!!
The quick and dirty way to fix this is to use a double-checked lock:
if(instance.Beta==10.0)
{
lock(instance)
{
if(instance.Beta==10.0)
{
instance.UpdateBeta(instance.Beta*10.0);
}
}
}
The same is true for CurrentPosition.
I have a CacheHelper class to facilitate interaction with the cache. I want to use a static int field to specify my cache timeout. The field is initially set to a const default value but I want to provide a way for the application to change the default timeout value.
Do you need to lock when modifying a static value type? Is the lock in the setter necessary? Are there any other problems you can see here? Sorry, I'm still pretty dumb when it comes to multithreading.
Thanks.
public static class CacheHelper
{
private static object _SyncRoot;
private static int _TimeoutInMinutes = CacheDefaults.TimeoutInMinutes;
public static int TimeoutInMinutes
{
get
{
return _TimeoutInMinutes;
}
set
{
lock (_SyncRoot)
{
if (_TimeoutInMinutes != value)
{
_TimeoutInMinutes = value;
}
}
}
}
public static void Insert(string key, Object data)
{
if (HttpContext.Current != null && data != null)
{
HttpContext.Current.Cache.Insert(key, data, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(CacheHelper.TimeoutInMinutes));
}
}
}
You could use a volatile variable instead... but you need something, otherwise it's possible that a value written by one thread would never be seen by another.
Note that for "larger" types such as double or long you really should use a lock or the Interlocked class, as modifications to those values may not be atomic.
You don't need to lock here if the client of CacheHelper does somthing like
CacheHelper.TimeoutInMinutes = input.Value;
Since it doesn't rely on the previous value.
If your client does something like
CacheHelper.TimeoutInMinutes += input.Value;
Then you'll need to do some locking
.