The problem that the Lamport clock is trying to solve is how can take a snapshot of a consistent run in order to only detect real deadlocks.

Trying to find the solution
We assume that all the processes have access to a global clock (that’s something that doesn’t exists, but we make this assumptions to try to solve the problem)

First solution (complicated it’s not convenient): $P_0$ sends a message like “send me the local state in the $t_p$ timestamp. So the process $p$ waits until the timestap to send the local state.

Another solution is to set a time $t_0 + \Delta$ and capture the snapshot in that instant. The problem is what if the message doesn’t arrive in time? We has to try again, and that’a a problem. This would work in case of existance of a global clock, that makes sure that no future messages can be send to the past.

Global clock doesn’t exist, so we need another solution.
</details>

[!Clock Condition] If then where is the timestamp. Note that the arrow in the other way is not true, since if the two events are not correlated nor one or the other happens before the other, they’re concurrent.

The clock condition is always true if there is a global clock, but since processes in a distributed system don’t have access to a global clock, there is a need to invent a new type of clock that has the clock condition.

Every time an event occurs in a process, it labels it with a serial number (1,2,3 etc.). If a process makes an event that sends a message to a process , labels it with the next number of the greatest next number between and .

Untitled

In this way, can reconstruct the run in a consistent one, and the problem is solved without the use of a global clock.

This new clock that we discovered is called Lamport clock, invented by Lamport in the 70s.

The order that sees may be slightly different from the real order, but it’s important since the order change happens between non-correlated events, so the two runs are both consistent.

Logical Clocks and stable messages

A Lamport clock is a type of logical clock. Logical clocks are all clocks that have the clock condition.

When receives a message, we make a difference between receiving and delivering:

  • Received means that the messages arrive at , but other messages previous to that one may still arrive in the future
  • Delivered means that the message is accepted by and can be processed since no other messages previous to that one can arrive in the future;

will deliver a message only if it’s stable.

[!Stable Message] Message is stable at if no message such that can arrive in the future.

The received message 2 is not stable because I still can receive a 1 in the future, and 1 < 2.

The received message 2 is not stable because I still can receive a 1 in the future, and 1 < 2.

A way that can recognize a message as stable is to implement channels as FIFO (First In First Out), in this way when it receives a message, it knows that all the previous messages have already arrived.

We define the array . In the start, is composed of zeros and has the length of the number of processes.

In this way, a message received from is stable only if all the other values in the vector are greater than the of the message received. That’s because in order to deliver a message, all the messages with the lower than the received message have to be delivered too, since the current message may depend on one of them.

TODO: Change the vectors because they’re wrong

Todo

TODO: Change the vectors because they’re wrong

This is a solution but it’s not perfect, since it can raise some problems.

The first problem is that, in order to deliver a message, the process has to wait for all the processes with lower TS to arrive, and this could cause the process to wait forever to deliver a message.

This can happen because a message with a low doesn’t arrive because of a failure.

Another cause could be seen in the picture: the message from with will not be delivered until a message with is received from and , and since ’s last message has , it will wait forever.

Strong clock condition

A strong clock condition is a clock condition that is valid in both ways.

Logical clocks don’t have this condition:

Untitled

In this picture, we can see how but it’s not true that , since they’re concurrent.

If two events in two processes are concurrent, it’s hard to assign them a numerical .

As we can see from the picture below, the timestamps 4-5 or 6-5 are not right because no event happens before one another. I cannot give them 5-5 because if then another event happens I would have 5-6, but it’s not true that the event with on the first process happens before the event on process 2 with .

Untitled

So we arrived at the fact that a numerical is not enough in order to have a strong clock condition.

Causal history

Note

🔁 Causal history of an event

The causal history is the set of events that may have contributed to the event .

Untitled

Note

If It’s true also in the other direction, since So it’s true that

In order to avoid the problems that the solution above raised, we can timestamp the messages with their causal history.

This obviously can bring problems with efficiency, since the causal history of an event can be very big.

Vector clock

To solve the problem of the causal history is big, we can timestamp an event not with the entire history, but with just the last event that’s part of the history, In this way all the other past processes in history become implicit.

Note

🕰️ Vector clock:

This type of clock has a strong clock condition.

Computed vector clocks for all the events in the processes

Computed vector clocks for all the events in the processes

If the vector is of the type , know that this is the 2nd message sent by , and it knows that that message doesn’t depend on or , since the values on those positions are zeros.

In case the last is and receives it cannot receive it because the message depends on two messages of that it didn’t receive yet.

With the Vector Clock, can deliver all the messages that can be delivered, different from before.

The vector that keeps to keep track means i received messages from , messages from , and messages from . The vector that keeps is not a TS, but it’s only a vector to make a comparison with the VC it will receive.