Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4237021

java.text.Collator.compare() is no longer thread safe

XMLWordPrintable

    • beta
    • generic
    • generic



      Name: krT82822 Date: 05/10/99


      /*
       * POET SDK Java Edition
       * Copyright (c) POET Software 1999
       *
       * Test module
       * kwz 10. May 1999, created
       */

      //// //// //// //// //// //// //// //// //// //// //// //// //// //// //// ////

      import java.text.*;
      import java.util.*;

      /**
       * The Collators of old JDK versions are thread safe.
       * JDK 1.2's Collator is not thread-safe.
       * Question to SUN: Is that the intended behavior or a bug?
       *
       * The test below compares a string to itself and
       * prints a line when the test result is != 0, which
       * should never happen. Each thread has its own String,
       * but shares the same Collator with other threads. Just call
       *
       * java CollatorTest
       *
       * With Java 1.2 I get lots of lines like
       * ConcurrentTestObject-4 == ConcurrentTestObject-4 but compare returns 1
       * ConcurrentTestObject-5 == ConcurrentTestObject-5 but compare returns 1
       * ConcurrentTestObject-6 == ConcurrentTestObject-6 but compare returns 1
       * ConcurrentTestObject-8 == ConcurrentTestObject-8 but compare returns 1
       * ConcurrentTestObject-9 == ConcurrentTestObject-9 but compare returns -1
       * ConcurrentTestObject-0 == ConcurrentTestObject-0 but compare returns -1
       * ConcurrentTestObject-1 == ConcurrentTestObject-1 but compare returns -1
       * ConcurrentTestObject-7 == ConcurrentTestObject-7 but compare returns 1
       *
       * java -version
       * java version "1.2"
       * Classic VM (build JDK-1.2-V, native threads)
       *
       * This happens in calls to RuleBasedCollator after version 1.23 98/05/20
       * Prior versions seem to work, I looked into the sources of 1.22 98/04/22
       * they do not contain this bug.
       *
       * From analyzing the sources it can be said that the later version of
       * RuleBasedCollator caches CollationElementIterator objects between the
       * calls to compare(). Unfortunately, it doesn't synchronize on them.
       * Thus, if two threads call compare() concurrently the state of the
       * iterators is undefined, resulting in undefined comparisons.
       *
       * The question is: is this intended behavior? Or did the programmer
       * just forget to synchronize?
       *
       * Problem: Old code, i.e., code only tested against the library of JDK1.1.6,
       * may be unaware of this problem and breaks with strange errors when used
       * with newer libraries.
       *
       * Since the documentation nowhere explicitely states that Collator.compare()
       * is no longer thread-safe, I would consider this a bug.
       *
       * A simple fix would be to place a synchronize( this )
       * around the bodies of all public methods that change the
       * internal state of RuleBasedCollator.
       *
       * A workaround is to synchronize externally or create a new Collator for
       * each Thread. But this means that old code would have to be changed.
       *
       *
       * @author Kai W. Zimmermann
       */

      public class CollatorTest
      {
      static Collator coll;

      private static class CollatorThread extends Thread {

      String myPrefix;
      int myNumber;
      public String string1;
      boolean doTestMany;

      public CollatorThread ( String prefix, int number, boolean doTestMany ) {
      myPrefix = prefix;
      myNumber = number;
      string1 = prefix + (number%10);
      this.doTestMany = doTestMany;
      }

      public void run () {
      if( doTestMany )
      testMany();
      else
      testOne();
      }


      public void testOne () {
      for( int i = 0; i<1000; ++i) {
      int result;
      result = coll.compare(string1,string1);
      if( result != 0 ) {
      // Oops, how comes?
      System.out.println( string1+" == "+string1+" but compare returns "+ result );
      }

      }
      }

      public void testMany () {
      for( int i = 0; i<1000; ++i) {
      int result;
      // result = coll.getCollationKey(string1).compareTo(coll.getCollationKey(myPrefix+(i%10)));
      result = coll.compare(string1,myPrefix+(i%10));
      if( (myNumber%10)<(i%10) ) {
      if( result != -1 ) {
      System.out.println( string1+" < "+(myPrefix+(i%10))+" but compare returns "+ result );
      }
      }
      else if( (myNumber%10)>(i%10) ) {
      if( result != +1 ) {
      System.out.println( string1+" > "+(myPrefix+(i%10))+" but compare returns "+ result );
      }
      }
      else {
      if( result != 0 ) {
      System.out.println( string1+" == "+(myPrefix+(i%10))+" but compare returns "+ result );
      }

      }
      }
      }

      }

      public static void main(String[] args)
      {
      coll = Collator.getInstance();
      coll.setStrength(Collator.TERTIARY);
      for( int j = 0; j<20; ++j ) {
      new CollatorThread("ConcurrentTestObject-",j,false).start();
      }
      }


      }
      (Review ID: 58024)
      ======================================================================

            bcbeck Brian Beck (Inactive)
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: