Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How thread-safe is enum in java?

How thread-safe is enum in java? I am implementing a Singleton using enum (as per Bloch's Effective Java), should I worry at all about thread safety for my singleton enum? Is there a way to prove or disprove that it is thread safe?

// Enum singleton - the preferred approach public enum Elvis {      INSTANCE;     public void leaveTheBuilding() { ... } } 

Thanks

like image 271
Lydon Ch Avatar asked Mar 28 '10 04:03

Lydon Ch


People also ask

How are enums safe?

The enums are type-safe means that an enum has its own namespace, we can't assign any other value other than specified in enum constants. Typesafe enums are introduced in Java 1.5 Version. Additionally, an enum is a reference type, which means that it behaves more like a class or an interface.

Why enum is best for Singleton?

Singleton With EnumSince enums are inherently serializable, we don't need to implement it with a serializable interface. The reflection problem is also not there. Therefore, it is 100% guaranteed that only one instance of the singleton is present within a JVM.

What is the advantage of enum in Java?

You can declare a function argument, return type, class member or local variable to be a particular Enum type and the compiler will enforce type safety; Enums are basically classes. They can implement interfaces, have behaviour and so on.

Are enums better than strings?

They are type safe and comparing them is faster than comparing Strings. Show activity on this post. If your set of parameters is limited and known at compile time, use enum . If your set of parameters is open and unkown at compile time, use strings.


2 Answers

As @Mike is saying, creation of enum is guaranteed to be thread safe. However, methods that you add to an enum class do not carry any thread safety guarantee. In particular, the method leaveTheBuilding may be executed, concurrently, by multiple threads. If this method has side effects (changes the state of some variable) then you need to think about protecting it (i.e., make it synchronized) or parts thereof.

like image 163
Itay Maman Avatar answered Sep 17 '22 21:09

Itay Maman


Customized Enum Definition may be not thread safe. For example,

RoleEnum.java:

package com.threadsafe.bad;  public enum RoleEnum {        ADMIN(1),        DEV(2),        HEAD(3);         private Integer value;        private RoleEnum(Integer role){               this.value=role;                   }        public static RoleEnum fromIntegerValue(Integer role){                for(RoleEnum x : values()){                      if(x.value == role ){                            return x;                      }               }               return RoleEnum.HEAD;                     }         Class<?> buildFromClass;        public void setBuildFromClass(Class<?> classType){               buildFromClass=classType;        }        public Class<?> getBuildFromClass(){               return this.buildFromClass;        } } 

Main.java:

package com.threadsafe.bad;  public class Main {         public static void main(String[] args) {               // TODO Auto-generated method stub                Thread threadA = new Thread(){                      public void run(){                            System.out.println("A started");                            RoleEnum role;                            role=RoleEnum.fromIntegerValue(1);                            System.out.println("A called fromIntegerValue");                            role.setBuildFromClass(String.class);                            System.out.println("A called setBuildFromClass and start to sleep");                              try {                                   Thread.sleep(10000);                            } catch (InterruptedException e) {                                   // TODO Auto-generated catch block                                   e.printStackTrace();                            }                            System.out.println("Thread A: "+role.getBuildFromClass());                      }               };                Thread threadB = new Thread(){                      public void run(){                            System.out.println("B started");                            RoleEnum role;                            role=RoleEnum.fromIntegerValue(1);                            role.setBuildFromClass(Integer.class);                            System.out.println("B called fromIntegerValue&setBuildFromClass and Start to sleep");                            try {                                   Thread.sleep(20000);                            } catch (InterruptedException e) {                                   // TODO Auto-generated catch block                                   e.printStackTrace();                            }                            System.out.println("B waked up!");                             System.out.println("Thread B: "+ role.getBuildFromClass());                      }                };                threadA.start();               threadB.start();          }  } 

Sometimes the output will be:

B started

B called fromIntegerValue&setBuildFromClass and Start to sleep

A started

A called fromIntegerValue

A called setBuildFromClass and start to sleep

Thread A: class java.lang.String

B waked up!

Thread B: class java.lang.String <-We expect java.lang.Integer

Sometimes the output will be:

A started

A called fromIntegerValue

A called setBuildFromClass and start to sleep

B started

B called fromIntegerValue&setBuildFromClass and Start to sleep

Thread A: class java.lang.Integer <-We expect java.lang.String

B waked up!

Thread B: class java.lang.Integer

like image 28
Jichao Zhang Avatar answered Sep 17 '22 21:09

Jichao Zhang