Sleeping barber problem in Erlang
Overall it looks good, I would just have some minor comments. In any case please have a look at the official Ericsson guidance.


Use macro ?MODULE instead of repeating sb.
In Erlang function names are usually_with_underscores rather than camelCasing. There are some exceptions, even in OTP applications, but in general underscores help to distinguish functions from variable names, which are usually CamelCased. The same holds for atom names.
I would usually put a code like this: [First | Rest] = Clients directly to the function argument to make it shorter, e.g.: tryAttend([First | Rest] = Clients, Barbers, BarberShopPID) -&gt;
NewC and NewB aren't very descriptive. I would rather use NClients if NewClients are too long for you.
When accessing the head and tail of a list the names of variables are usually H and T, unless you want a specific name for the head, in which case the tail is just T or Tail, e.g. [H|T] = Clients or [First|T] = Clients. It's a convention which you will notice when reading someone else's code.
When spawning process with a function that doesn't need to be exported for its own sake try to use fun, e.g.: spawn(fun() -&gt; barber(First, BarberShopPID) end). It's better to not expose functions that are not meant to be called from outside. And if you do have to export a function like that, then it's better to put it into a separate export with an additional comment, e.g. %% Internal API.
Didn't you want to write MAX_SEATS rather than MAX_SITS? :)