0

i have a student question:

i would like to have an advice and some explanation about visibility problem in multicore if there is one.

I use Registry pattern in my SpringBoot Application to map different scanners instances to their names.

Configuration:

@Bean
public WebScannerExecutor webScannerExecutor(final WebScannerClientProcessor webScannerClientProcessor) {
    return new WebScannerExecutor(webScannerClientProcessor);
}

@Bean
public TLSScannerExecutor tlsScannerExecutor(final @Value("${tls.scanner.path}") String path, final BashProcessor bashProcessor) {
    return new TLSScannerExecutor(path, bashProcessor);
}

@Bean
public ScanExecuterRegistry executerRegistry(final WebScannerExecutor webScannerExecutor, final TLSScannerExecutor tlsScannerExecutor) {
    final ScanExecuter[] arr = new ScanExecuter[] {webScannerExecutor, tlsScannerExecutor};
    return new ScanExecuterRegistry(arr);
}

Registry:

public class ScanExecuterRegistry {

private final ImmutableMap<ScannerType, ScanExecuter> registry;

 public ScanExecuterRegistry(final ScanExecuter... executors) {
        this.registry = ImmutableMap.<ScannerType, ScanExecuter> builder().putAll(Arrays.asList(executors).stream().collect(Collectors.toMap(ScanExecuter::getType, e -> e))).build();
    }

Right now i am using ImmutableMap from Guava and i am pretty sure there is no problem. But...

private final Map<ScannerType, ScanExecuter> registry;

If i take instead of ImmutableMap just a final map (immutable reference but not content), could any problem rise? Any problem with thread caches, visibility et cetera in multicore systems (even with the usage of singeltons)?

EDITED:

All good as long as you don't modify the content

Exactly that i would like to get explained. I am not so good with java memory model yet.

I can change the content of map, only in spring configuration class adding a new scanner. So the application will restart in any case. Can there still be a problem?

GreedyHat
  • 5
  • 3
  • All good as long as you don't modify the content, compare http://stackoverflow.com/questions/6457109/java-concurrency-is-final-field-initialized-in-constructor-thread-safe – zapl Dec 13 '16 at 10:33

1 Answers1

2

To be sure that a variable shared in a multithread environment doesn't cause errors you need to ensure that:

  • The variable is immutable or
  • The variable is mutable, but the access to that variable is synchronized or
  • The variable is mutable, but you don't change its value after creating it (*).

If you replace an ImmutableMap with a mutable Map (for example an HashMap) all works if that Map is not muted after it is shared between threads.

Note that defining a variable as final doesn't ensure that its content never change. final, for objects, means only that the reference can't be changed, but it is possible for example to add, remove or change items to a final Map.


(*) Note: as explained by @bowmore it is necessarely to guarantee a safe publication of the shared variable:

Safe publication makes all the values written before the publication visible to all readers that observed the published object

This can be done with:

  • Initializing an object reference from a static initializer.
  • Storing a reference to it into a volatile field.
  • Storing a reference to it into a final field.
  • Storing a reference to it into a field that is properly guarded by a (synchronized) lock.
Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56