Allowing a method to lock its parent Object in Java
Asked Answered
A

4

4

Is there a way in Java to get a method to lock (mutex) the object which it is in?

I know this sounds confusing but basically I wan't an equivelent to this snippet of C# but in Java.

lock(this)
{
    // Some code here...
}

I've been tasked with reimplementing an API written in .Net into Java, and I've been asked to keep the Java version as similar to the .Net version as humanly possible. This isn't helped by the fact that the .Net version looked like it was transcribed from a C++ version which I don't have access to.

Anyway the above line appears in the C# version and I need something that does the same in Java.

Azucenaazure answered 13/1, 2009 at 15:16 Comment(0)
W
13

The equivalent of that is:

synchronized (this)
{
}

(And no, you shouldn't generally do it in either C# or Java. Prefer locking on private references which nothing else has access to. You may be aware of that already, of course - but I didn't want to leave an answer without the warning :)

Wiencke answered 13/1, 2009 at 15:19 Comment(13)
Thanks Jon, I was convinced I'd tried that and Eclipse was moaning about it. Maybe I'd mis-spelt synchronised and hadn't noticed.Azucenaazure
Why should you prefer to lock private references? See also stackoverflow.com/questions/416183/…Basseterre
Because then other code can't expectedly lock on you. It's like exposing more methods than you have to - but harder to debug, because threading is fundamentally hard.Wiencke
See item 70 in the second edition of Effective Java for more details - and also how to lock when you do have to use public references as part of the API.Wiencke
I've read the item and I still feel that "you shouldn't generally do it" is overstated (esp. considering the scope of the question). I would say: it is something typical to do. "Threading is fundamentally hard" is something you can throw at almost anything, but no one will be any wiser.Basseterre
eljenso: I think we'll have to agree to disagree. The fact that threading is hard makes it all the more important to be as careful as you can - and making it impossible for other code to accidentally lock on the same thing you're locking on count as being careful IMO. (continued)Wiencke
If you want to expose the lock, then that's one thing - but otherwise, what benefit is there in locking on something which others might lock on? There's the tiny, tiny benefit of not having to create a new object - but that's basically it. See also P636-639 of Jeff Richter's CLR via C#.Wiencke
(I'll check whether Joe Duffy's latest book has a similar entry when I get back tonight. I thought it was pretty much understood and accepted guidance these days, in the same manner as not exposing fields publicly...)Wiencke
I don't mind being wrong on this one, I will actually learn something from it. I just need good examples (no foo-bar stuff). I definitely want to know more, maybe a new question is needed here? I'm at "work" right now (yeah right) so I'll have to continue this later as well.Basseterre
Yup, a new question could raise some interesting discussion. It's not so much a "right or wrong" question as "defensive practices". As with a lot of best practices, it's more important for class library design (where you don't know the consumer) than straight app development.Wiencke
Great answer, but I do think that "threading is fundamentally hard" is unhelpful (although perhaps true). It too easily becomes an excuse for programmers not to learn threading properly.Semple
I think the context is important here - I was using "threading is fundamentally hard" as a reason to pay even more attention to best practices and defensive coding when it comes to threading than elsewhere. Apologies if that wasn't clear.Wiencke
Continued at stackoverflow.com/questions/442564/…Basseterre
P
6

Assuming that the C++ code is a simple mutex, replace "lock" with "synchronized"

synchronized (this)
{
// ...
}

Here's the Java Concurrency tutorial for more info

Psych answered 13/1, 2009 at 15:21 Comment(0)
A
1

I'd recommend Brian Goetz's "Java Concurrency In Practice." It's an excellent book.

It can be a good thing to keep the synchronized block as small as possible. Using the synchronized modifier on the method is coarse-grained and sometimes necessary, but otherwise you can use another object to do it that keeps the block smaller.

Like this:

public class PrivateLock {
    private final Object myLock = new Object();
    @GuardedBy("myLock") Widget widget;

    void someMethod() {
        synchronized (myLock) {
            // Access or modify the state of widget
        }
    }
}
Ation answered 13/1, 2009 at 15:38 Comment(0)
D
1

You should also look into the java.util.concurrent package of the API (JDK 5.0+) for additional concurrency management objects such as semaphore, exchanger, etc

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/package-summary.html

Dukie answered 13/1, 2009 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.