Kevin Kostlan
Kevin Kostlan

Reputation: 3519

MATLAB synchronized code

What is the equivalent to Java's "synchronized" in MATLAB?

Suppose I have two timers, and they both can modify a variable (i.e. matrix) M. If they fire at the same time, will they both try to change M at once (which could cause errors)? Does MATLAB automatically synchronize such operations?

Upvotes: 3

Views: 1572

Answers (1)

Pursuit
Pursuit

Reputation: 12345

Matlab is 99% single threaded (the other 1% is not really relevant to this question). So no synchronized keyword is available.

However, some operations are interruptible, which means that GUI callbacks or Timers can pause operation at unexpected times. This can cause some of the same problems that can be observed in multi-theaded systems.

To prevent interruptions, use the interruptible property when it is available (generally on GUI objects). This should handle the need to prevent reentrant behavior when dealing with GUI callbacks. E.G.

set(gcf,'Interruptible','off')

However, this does not handle interruptions related to timers.


It appears that two timers cannot interrupt each other, so no synchronization is needed. However, a timer can interrupt the main activity.

After some testing, this can occur near a pause, drawnow, figure, or getframe call, which is implied in the documentation. It can also occur near other calls, including some tic/toc calls and calls to Java.

I am not aware of a parallel to the Interruptible property for either timers or functions, even though it may be needed. The root object 0 has an Interruptible property, but it has no effect (per documentation, and confirmed).

Note: this is a large change from a previous answer I supplied (see history), representing recent learning. My previous example used two timers, which appear to deconflict with each other. This example uses one timer plus main function operation.


An example is included below, demonstrating one un-interruptible case, and two cases where the function some_work is interrupted.

function minimum_synchronization_example

%Defune functions to test for interruptability
%(these are all defined at the bottom of the file)
fnList = {
    @fn_expectedNoInterruption
    @fn_expectedInterruption
    @fn_unexpectedInterruption
    };
for ix = 1:length(fnList)
    disp(['---Examples using ' func2str(fnList{ix}) '--------'])
    test_subfunction_for_interrupt_allowed(fnList{ix});
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function test_subfunction_for_interrupt_allowed(fn)
%Setup and start a timer to execute "some_work"
t1 = timer();
set(t1,...
    'Name','PerformSomeWorkTimer1', ...
    'TimerFcn', @(~,~) some_work('Timer-1', fn), ...
    'ExecutionMode','fixedSpacing', ...
    'Period', 0.4, ...
    'TasksToExecute', 6, ...
    'BusyMode', 'drop')
start(t1);

%Then immediately execute "some_work" from the main function
for ix = 1:6
    some_work('MainFun', fn);
    pause(0.2);
end

%The timer and the loop take about the same amount of time, stop and delete
%the timer before moving on
stop(t1);
delete(t1);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function some_work(displayString, subFunctionWhichMayAllowInterrupts)
%Initialize persistent, if needed.
%This records then umber of active calls to this function.
persistent entryCount
if isempty(entryCount)
    entryCount = 0;
end

%Record entry
entryCount = entryCount+1;
tic;

%Perform some work  (Inverting a 3000-by-3000 matrix takes about 1 sec on my computer)
[~] = inv(randn(3000));

%Run subfunction to see if it will be interrupted
subFunctionWhichMayAllowInterrupts();

%Display results. How many instances of this function are currently active?
if entryCount>1;
    strWarning = 'XXX ';
else
    strWarning = '    ';
end
disp([strWarning ' <' sprintf('%d',entryCount) '> [' displayString '] ; Duration: ' sprintf('%7.3f',toc)]);

%Record exit
entryCount = entryCount-1;
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function fn_expectedNoInterruption
x = 1+1;
end

function fn_expectedInterruption
drawnow;
end

function fn_unexpectedInterruption
m = java.util.HashMap();
end

Upvotes: 3

Related Questions