aspose file tools*
The moose likes Threads and Synchronization and the fly likes Specific threads question.... Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Specific threads question...." Watch "Specific threads question...." New topic
Author

Specific threads question....

Anthony Smith
Ranch Hand

Joined: Sep 10, 2001
Posts: 285
I have a class that has a main, implements runnable...
Right now my main class will call one of my methods depending on my input

For this one particular method it opens a file and then creates threads calling their run methods via start().

My class has three members that I use
String buffer ="";
static BufferedReader dis;
static PrintWriter out;

In my method that creates the threads, I open a file for reading and open a file for writing.

In my run method, I use dis to read the file and out to write to the file. buffer is what I am reading from the input file, and buffer is also what
I am writing to the output file...

Originally, I was just reading from a file and doing no writing to a file.

Tis seemed to work:

synchronized(buffer){
buffer = dis.readLine();
out.println(buffer);
}

I thought that that kind of synchronization would work... For some reason, I don't think that is the best way...

What should I do so that a thread is not accessing the input and putput file at the same time?

Also, should I create a local variable in my run method to assign buffer to? I use buffer to perform some other operations later on in my run method...
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Keep in mind that synchronization locks are obtained on an instance of an object -- not on a reference variable. When you assign a new String to buffer, the other threads will now be able to synchronize on it since the current thread holds a lock on the String that buffer used to reference.

Instead, create a single object (heck, us an actual Object instance if you like) on which to synchronize, or synchronize on the instance of the main class itself by having the run() method call a synchronized method on the main class.

I definitely recommend making buffer local to the run() method since it's not shared across threads. I wonder, however, what the point of using multiple threads is if you're synchronizing access to the file. Does each thread's run() method look something like the following?
  • Synchronize on file
  • Read line
  • Process line
  • Write line back to file
  • Release lock on file

  • If so, then having multiple threads do this same loop adds only overhead since the whole set of five steps must occur in a block. If you describe what the purpose is in more detail we can offer other ideas.
    [ March 15, 2005: Message edited by: David Harkness ]
    Anthony Smith
    Ranch Hand

    Joined: Sep 10, 2001
    Posts: 285
    Ok, you kind of confused me just a bit...

    I do understand the part about making buffer local. I dont know why I tried to make it global. Now the making an object... I have no clue about that.

    Here is the method called from my main:
    public static void readFileAndRate(){

    String input = "C:\\autopay\\testfiles\\CO_OB.txt";
    try{
    InputStreamReader bis = new InputStreamReader(new FileInputStream(input));
    dis = new BufferedReader(bis);
    out = new PrintWriter(new FileOutputStream("OB_Status.txt"));
    }
    catch(Exception e){
    e.printStackTrace();
    }

    for (int i = 0; i!=10; i++){
    new Thread(new ECQSClientBeanTester()).start();
    }

    }

    *******************************************
    Here is my run Method:

    public void run(){

    try{
    while (true) {

    synchronized(buffer){
    buffer = dis.readLine();
    out.println(buffer);
    }

    Make some external calls to other methods with
    the value of buffer as my input
    ..........

    }
    Henry Wong
    author
    Sheriff

    Joined: Sep 28, 2004
    Posts: 18845
        
      40

    What you did is actually a pretty common mistake:



    Basically, synchronization is done with an object (as a monitor). Upon entry to synchronization, the JVM will grab the lock of the object referred to by the buffer variable.

    Changing the variable -- as you do in the next line -- is perfectly okay. But you have to understand, that if another thread does a synchronization on buffer, it is a different object, and hence, a different lock.

    Did you intend to have a different lock? Or are you assuming that all blocks that synchronized on the buffer variable are thread safe?

    Henry


    Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
    Anthony Smith
    Ranch Hand

    Joined: Sep 10, 2001
    Posts: 285
    Ah... Sounds like I need to get a java book... I have no idea what to do.
    Yuriy Zilbergleyt
    Ranch Hand

    Joined: Dec 13, 2004
    Posts: 429
    Unless one of the other methods you call reassigns dis or out (or readFileAndRate() gets called again,) you can synchronize on either one of these:


    synchronized(dis){
    buffer = dis.readLine();
    out.println(buffer);
    }

    Since unlike buffer, dis always points to the same object, you'll never have more than one thread executing the synchronized block at a time.

    -Yuriy
     
    It is sorta covered in the JavaRanch Style Guide.
     
    subject: Specific threads question....