• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Specific threads question....

 
Ranch Hand
Posts: 285
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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...
 
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
    Posts: 285
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
    ..........

    }
     
    author
    Posts: 23951
    142
    jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
     
    Anthony Smith
    Ranch Hand
    Posts: 285
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Ah... Sounds like I need to get a java book... I have no idea what to do.
     
    Ranch Hand
    Posts: 429
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
     
    reply
      Bookmark Topic Watch Topic
    • New Topic